HDOJ 4267 A Simple Problem with Integers(线段树)

来源:互联网 发布:淘宝开店教程ppt 编辑:程序博客网 时间:2024/06/06 19:22
/*显然这道题应该用线段树来做,区间更新、多次查找,然而线段树中状态比较多,需要用多个线段树来表示这些状态。原来线段树中c[][]为一个二维数组,c[k][u],其中k表示余数,u表示a%k,这样共有55种情况,不过最后内存超,然后用一维表示,通过。思路:(i - a) % k == 0 可以等效于 i % k == a % k*/#include <cstdio>#include <cstring>const int nMax = 50001;struct Tree{int l, r;int c[57];//[11][11];}tree[nMax * 4];int A[nMax];int N, Q;void build(int rt, int l, int r){if(l < r){int mid = (l + r) / 2;build(rt * 2, l, mid);build(rt * 2 + 1, mid + 1, r);}tree[rt].l = l;tree[rt].r = r;memset(tree[rt].c, 0, sizeof(tree[rt].c));}void update(int rt, int u, int k, int l, int r, int c){if((tree[rt].l == l) && (tree[rt].r == r)){int index = k * (k - 1) / 2 + u;tree[rt].c[index] += c;}else{int mid = (tree[rt].l + tree[rt].r) / 2;if(r <= mid)update(rt * 2, u, k, l, r, c);else if(mid + 1 <= l)update(rt * 2 + 1, u, k, l, r, c);else{update(rt * 2, u, k, l, mid, c);update(rt * 2 + 1, u, k, mid + 1, r, c);}}}void search(int rt, int a, int &w){int i;for(i = 1; i <= 10; ++ i){int index = i * (i - 1) / 2 + a % i;if(tree[rt].c[index] != 0)w += tree[rt].c[index];}if(tree[rt].l == tree[rt].r) return;int mid = (tree[rt].l + tree[rt].r) / 2;if(a <= mid)search(rt * 2, a, w);else if(mid + 1 <= a)search(rt * 2 + 1, a, w);}int main(){//freopen("e://data.in", "r", stdin);//freopen("e://data2.out", "w", stdout);int a, b, k, c;int i;while(scanf("%d", &N) != EOF){for(i = 1; i <= N; ++ i) scanf("%d", &A[i]);build(1, 1, N);scanf("%d", &Q);while(Q --){int t;scanf("%d", &t);if(t == 1){scanf("%d%d%d%d", &a, &b, &k, &c);update(1, a % k, k, a, b, c);}else{scanf("%d", &a);int w = 0;search(1, a, w);printf("%d\n", w + A[a]);}}}return 0;}

原创粉丝点击