http://acm.hdu.edu.cn/showproblem.php?pid=4027
题意:给出一个为 n 的区间, 1 - n 分别有相对应的值(大小为2^63)。 有两种操作, 一是改变从 i - j 区间的值, 改变方法是把 i - j 区间每个数都开方, 而是求从 i - j 区间这些数 的总和。
分析:因为这个操作是把一个数变成平方根,所以显得略棘手,不过如果仔细演算的话会发现一个2^64数的平方根开8次也就变成了 1,所以也更新不了多少次,所以可以每次更新到底。
注意:给的X Y大小未知,会出现X > Y的情况
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <math.h> #include <vector> using namespace std; typedef long long LL; const int oo = 0xfffffff; const int maxn = 110007; #define lson rt<<1 #define rson rt<<1|1 __int64 A[maxn]; /* 注意到2的63次方 开根号8次就到1了,所以判断rt左右两边端点值是否为1 */ struct node { int l, r, flag; __int64 sum; } tree[maxn<<2]; void build(int l, int r, int rt) { tree[rt].l = l; tree[rt].r = r; tree[rt].flag = 0; if(l==r) { tree[rt].sum = A[l]; if(tree[rt].sum==1) tree[rt].flag=1; return ; } int mid=(l+r)/2; build(l, mid , lson); build(mid+1, r, rson); tree[rt].sum = tree[lson].sum + tree[rson].sum; if(tree[lson].flag == 1 && tree[rson].flag == 1) tree[rt].flag = 1; } void update(int l, int r, int rt) { if(tree[rt].flag == 1) return ; if(tree[rt].l == tree[rt].r) { tree[rt].sum = (__int64)sqrt(tree[rt].sum); if(tree[rt].sum == 1) tree[rt].flag = 1; return ; } int mid = (tree[rt].l + tree[rt].r)/2; if(r<=mid) update(l, r, lson); else if(l>mid) update(l, r, rson); else { update(l, mid, lson); update(mid+1, r, rson); } //从头到尾得再重新更新值 tree[rt].sum = tree[lson].sum + tree[rson].sum; if(tree[lson].flag == 1 && tree[rson].flag ==1) tree[rt].flag = 1; } __int64 query(int l, int r, int rt) { if(tree[rt].flag == 1) return r-l+1; if(tree[rt].l == l && tree[rt].r == r) return tree[rt].sum; int mid = (tree[rt].l + tree[rt].r)/2; if(r<=mid) return query(l, r ,lson); else if(l>mid) return query(l, r, rson); else { __int64 lsum, rsum; lsum = query(l, mid, lson); rsum = query(mid+1, r, rson); return lsum+rsum; } } int main() { int n, q, i, cnt=1; while(scanf("%d",&n) != EOF) { for(i=1; i<=n; i++) scanf("%I64d",&A[i]); build(1, n, 1); scanf("%d",&q); printf("Case #%d: ",cnt++); while(q--) { int a, b, c; scanf("%d %d %d", &a, &b, &c); int t=c; if(b>c) { t=b; b=c; c=t; } if(a) { printf("%I64d ",query(b, c, 1)); continue; } update(b, c, 1); } printf(" "); } return 0; }