ACM-ICPC 2018 徐州賽區網路預賽(I + H)(水模擬 + 線段樹)
阿新 • • 發佈:2018-12-24
I
題意
給定一個字串和一個字元,將所有的 轉化為一個兩位數後,按順序拼接在一起,問,這個拼接而成的新序列,去掉前導0後的長度是多少
思路
按照模擬去實現一下過程就可以,可以計算前導零的個數,就不用算出所有的值了,現給出一種純模擬的寫法
程式碼
int a[maxn];
char s[maxn], ch;
int main()
{
int T;
sd(T);
while(T--){
int n, now = 0, ans = 1;
scanf("%d %c ", &n, &ch);
if(n==0) {
puts("1");
continue;
}
ss(s);
rep(i, 0, n){
int t = abs((int)(ch-s[i]));
a[now++] = t/10;
a[now++] = t%10;
}
rep(i, 0, 2*n){
if(a[i] != 0) {
ans = 2 *n-i;
break;
}
}
pd(ans);
}
return 0;
}
H
題意
給出一個長度為 的序列, 次詢問:
詢問,其中是區間的長度。
表示將序列中第 個數設定為
思路
題目是一眼看過去就知道是線段樹的題,那麼就變成了我們怎麼往線段樹上去考慮了。
從線段樹的思想入手,線段樹能解決區間問題的原因是,我們可以對區間維護的值進行合併,而這樣的一個類似梯度的求和,我們相當於維護了兩個區間的和 , 區間的”梯度和”(所求部分), 以及區間的長度 , 用線段樹來表示的話,我們可以得到這樣一個維護方程
程式碼
struct Node{
int l, r, len;
ll sum, ans;
}tree[maxn<<2]; //開四倍空間
ll num[maxn]; //數值陣列
void build(int i, int l, int r){
tree[i].l = l;
tree[i].r = r;
tree[i].len = (r-l+1);
if(l == r){
tree[i].sum = num[l];
tree[i].ans = num[l];
return ;
}
int mid = (l+r)>>1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r); //子樹建樹後更新特徵值
tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
tree[i].ans = tree[i<<1].ans + tree[i<<1|1].ans + tree[i<<1].sum*tree[i<<1|1].len;
return ;
}
void setx(int i, int x, int k){ // num[x] = k
if(tree[i].l == tree[i].r) {
tree[i].sum = k;
tree[i].ans = k;
return ;
}
int mid = (tree[i].l+tree[i].r)>>1;
if(x <= mid) setx(i<<1, x, k);
else setx(i<<1|1, x, k);
tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
tree[i].ans = tree[i<<1].ans + tree[i<<1|1].ans + tree[i<<1].sum*tree[i<<1|1].len;
}
ll querys(int i, int l, int r) {
if(tree[i].l==l && tree[i].r==r)
return tree[i].sum;
int mid = (tree[i].l+tree[i].r)>>1;
if(mid >= r)
return querys(i<<1, l, r);
else if(mid < l)
return querys(i<<1|1, l, r);
else
return querys(i<<1, l, mid) + querys(i<<1|1, mid+1, r) ;
}
ll querya(int i, int l, int r) {
if(tree[i].l==l && tree[i].r==r)
return tree[i].ans;
int mid = (tree[i].l+tree[i].r)>>1;
if(mid >= r)
return querya(i<<1, l, r);
else if(mid < l)
return querya(i<<1|1, l, r);
else
return querya(i<<1, l, mid) + querya(i<<1|1, mid+1, r) + querys(i<<1, l, mid)*(r-mid);
}
int main() {
int n, q;
sdd(n, q);
rep(i, 1, n+1)
sld(num[i]);
build(1, 1, n);
rep(i, 0, q) {
int op, l, r;
sddd(op, l, r);
if(op == 1){
printf("%lld\n", querya(1, l, r));
}
else {
setx(1, l, r);
}
}
return 0;
}