给出了一个序列,你需要处理如下两种询问。 "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。 "Q a b" 询问[a, b]区间中所有值的和。 Input 第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000. 第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。 接下来Q行询问, Sample Input 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 Sample Output 4 55 9 15
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; #define MAXSIZE 100005 long long val[MAXSIZE]; long long add[100010<<2]; long long sum[100010<<2]; long long sum1; struct node { long long total; int left; int right; int mark; //延时标记 } tree[MAXSIZE*3]; //下面两种create都可以,选择一种就可 long long create(int root,int left,int right) { add[root]=0; sum[root]=1; tree[root].left=left; tree[root].right=right; if(left==right) return tree[root].total=val[left]; int middle=(left+right)>>1; return tree[root].total=create(root<<1,left,middle)+create(root<<1|1,middle+1,right); } // 参数:询问区间左端点,询问区间右端点,每个位置需要增加的值,当前节点序号 void update(int L, int R, int x, int root) { if (L<=tree[root].left && tree[root].right<= R) { // 当前区间被包含,处理相应附加信息 add[root] += x; // 更新延迟标记 tree[root].total+= x * (tree[root].right-tree[root].left+1); return; // 暂时不用再向下递归 } int mid = (tree[root].left+tree[root].right)>>1; if (add[root]) // 延迟标记不为0,说明有未完成的更新,更新之 { add[root<<1] += add[root]; add[root<<1|1] += add[root]; tree[root<<1].total += add[root] * (mid-tree[root].left+1); tree[root<<1|1].total += add[root] * (tree[root].right-mid); add[root] = 0; // 不要忘了去除延迟标记 } if (L <= mid) // 左子区间中包含有更新区间的部分,需要更新 update(L, R, x, root<<1); if (R > mid) // 右子区间中包含有更新区间的部分,需要更新 update(L, R, x, root<<1|1); tree[root].total = tree[root<<1].total + tree[root<<1|1].total;//从叶子节点向上更新 } /* void find(tree *r,int a,int b){ if(r->left==a&&r->right==b){ sum+=r->data; return; } int mid=(r->left+r->right)>>1; if(b<=mid) find(r->lchild,a,b); else if(a>mid) find(r->rchild,a,b); else{ find(r->lchild,a,mid); find(r->rchild,mid+1,b); } }*/ //long long sum1; long long cal(int root,int a,int b){ if(a<=tree[root].left&&b>=tree[root].right){ return tree[root].total; } int mid=(tree[root].left+tree[root].right)>>1; if(add[root]){ add[root<<1] += add[root]; add[root<<1|1] += add[root]; tree[root<<1].total += add[root] * (mid-tree[root].left+1); tree[root<<1|1].total += add[root] * (tree[root].right-mid); add[root] = 0; // 不要忘了去除延迟标记 } if(b<=mid) return cal(root<<1,a,b); else if(a>mid) return cal(root<<1|1,a,b); else{ return cal(root<<1,a,mid)+cal(root<<1|1,mid+1,b); } } int main(){ int n,q; while(scanf("%d%d",&n,&q)!=EOF){ for(int i=1;i<=n;i++){ scanf("%lld",&val[i]); } memset(sum,0,sizeof(sum)); memset(add,0,sizeof(add)); long long tmp=create(1,1,n); char c; getchar(); int a,b,d; for(int i=1;i<=q;i++){ scanf("%c",&c); if(c=='C'){ scanf("%d %d %d",&a,&b,&d); update(a,b,d,1); } else{ scanf("%d%d",&a,&b); sum1=cal(1,a,b); printf("%lld ",sum1); } getchar(); } } return 0; }
/* POJ 3468 A Simple Problem with Integers 题目意思: 给定Q个数:A1,A2,```,AQ,以及可能多次进行下列两个操作: 1)对某个区间Ai```Aj的数都加n(n可变) 2)对某个区间Ai```Aj求和 */ #include<stdio.h> #include<algorithm> #include<iostream> usingnamespace std; constint MAXN=100000; int num[MAXN]; struct Node { int l,r;//区间的左右端点 longlong nSum;//区间上的和 longlong Inc;//区间增量的累加 } segTree[MAXN*3]; void Build(int i,int l,int r) { segTree[i].l=l; segTree[i].r=r; segTree[i].Inc=0; if(l==r) { segTree[i].nSum=num[l]; return; } int mid=(l+r)>>1; Build(i<<1,l,mid); Build(i<<1|1,mid+1,r); segTree[i].nSum=segTree[i<<1].nSum+segTree[i<<1|1].nSum; } void Add(int i,int a,int b,long long c)//在结点i的区间(a,b)上增加c { if(segTree[i].l==a&&segTree[i].r==b) { segTree[i].Inc+=c; return; } segTree[i].nSum+=c*(b-a+1); int mid=(segTree[i].l+segTree[i].r)>>1; if(b<=mid) Add(i<<1,a,b,c); elseif(a>mid) Add(i<<1|1,a,b,c); else { Add(i<<1,a,mid,c); Add(i<<1|1,mid+1,b,c); } } longlong Query(int i,int a,int b)//查询a-b的总和 { if(segTree[i].l==a&&segTree[i].r==b){ return segTree[i].nSum+(b-a+1)*segTree[i].Inc; } segTree[i].nSum+=(segTree[i].r-segTree[i].l+1)*segTree[i].Inc; int mid=(segTree[i].l+segTree[i].r)>>1; Add(i<<1,segTree[i].l,mid,segTree[i].Inc); Add(i<<1|1,mid+1,segTree[i].r,segTree[i].Inc); segTree[i].Inc=0; if(b<=mid) return Query(i<<1,a,b); else if(a>mid) return Query(i<<1|1,a,b); else return Query(i<<1,a,mid)+Query(i<<1|1,mid+1,b); } int main() { int n,q; int i; int a,b,c; char ch; while(scanf("%d%d",&n,&q)!=EOF) { for(i=1; i<=n; i++) scanf("%d",&num[i]); Build(1,1,n); for(i=1; i<=q; i++) { cin>>ch; if(ch=='C') { scanf("%d%d%d",&a,&b,&c); Add(1,a,b,c); } else { scanf("%d%d",&a,&b); printf("%I64d ",Query(1,a,b)); } } } return0; }