线段树基础题,除线段树外至少还有2种做法:树状数组,Splay
A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. Input The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. Output You need to answer all Q commands in order. One answer in a line. 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 Hint
The sums may exceed the range of 32-bit integers.
Source
POJ Monthly--2007.11.25, Yang Yi
|
[Submit] [Go Back] [Status] [Discuss]
树状数组的改段求段操作:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=2100100; int n,q; long long int b[maxn],c[maxn]; void init() { memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); } int lowbit(int x) { return x&(-x); } void add_b(int p,long long int v) { for(int i=p;i;i-=lowbit(i)) b[i]+=v; } void add_c(int p,long long int v) { for(int i=p;i<maxn;i+=lowbit(i)) c[i]+=p*v; } long long int sum_b(int p) { long long int ret=0; for(int i=p;i<maxn;i+=lowbit(i)) ret+=b[i]; return ret; } long long int sum_c(int p) { long long int ret=0; for(int i=p;i;i-=lowbit(i)) ret+=c[i]; return ret; } void ADD(int L,int R,long long int v) { add_b(R,v); add_c(R,v); if(L-1) { add_b(L-1,-v); add_c(L-1,-v); } } long long int sUm(int p) { if(p==0) return 0; return sum_b(p)*p+sum_c(p-1); } long long int SUM(int L,int R) { return sUm(R)-sUm(L-1); } int main() { while(scanf("%d%d",&n,&q)!=EOF) { init(); for(int i=1;i<=n;i++) { int v; scanf("%d",&v); ADD(i,i,v); } while(q--) { char str[10]; scanf("%s",str); if(str[0]=='Q') { int l,r; scanf("%d%d",&l,&r); printf("%I64d\n",SUM(l,r)); } else if(str[0]=='C') { int l,r; long long int v; scanf("%d%d%I64d",&l,&r,&v); ADD(l,r,v); } } } return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long int LL; const int maxn=100100; const int INF=0x3f3f3f3f; #define Key_value ch[ch[root][1]][0] int pre[maxn],ch[maxn][2],key[maxn],size[maxn],a[maxn]; int n,m; LL add[maxn],sum[maxn]; int root,tot; /*******************debug*******************/ void Debug(int x) { if(x) { Debug(ch[x][0]); cout<<"节点:"<<x<<" Key: "<<key[x]<<" left_son: "<<ch[x][0]<<" right_son: "<<ch[x][1] <<" size: "<<x<<" Sum: "<<sum[x]<<endl; Debug(ch[x][1]); } } /*******************************************/ void NewNode(int& r,int father,int k) { r=++tot; pre[r]=father; ch[r][0]=ch[r][1]=add[r]=0; sum[r]=key[r]=k; size[r]=1; } void Update_Add(int x,int v) { if(x==0) return ; sum[x]+=(LL)size[x]*v; key[x]+=v; add[x]+=v; } void Push_Up(int x) { sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x]; size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void Push_Down(int x) { if(add[x]) { Update_Add(ch[x][0],add[x]); Update_Add(ch[x][1],add[x]); add[x]=0; } } void Build(int &x,int l,int r,int father) { if(l>r) return ; int m=(l+r)>>1; NewNode(x,father,a[m]); Build(ch[x][0],l,m-1,x); Build(ch[x][1],m+1,r,x); Push_Up(x); } void Init() { tot=root=0; ch[root][0]=ch[root][1]=pre[root]=key[root]=sum[root]=add[root]=size[root]=0; NewNode(root,0,-INF); NewNode(ch[root][1],root,INF); for(int i=1;i<=n;i++) scanf("%d",a+i); Build(Key_value,1,n,ch[root][1]); Push_Up(ch[root][1]); Push_Up(root); } void Rotate(int x,int kind) { int y=pre[x]; Push_Down(y); Push_Down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; Push_Up(y); } void Splay(int r,int goal) { Push_Down(r); while(pre[r]!=goal) { if(pre[pre[r]]==goal) { Push_Down(pre[r]); Push_Down(r); Rotate(r,ch[pre[r]][0]==r); } else { Push_Down(pre[pre[r]]); Push_Down(pre[r]); Push_Down(r); int y=pre[r]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==r) Rotate(r,!kind); else Rotate(y,kind); Rotate(r,kind); } } Push_Up(r); if(goal==0) root=r; } int Get_Kth(int r,int x) { Push_Down(r); int t=size[ch[r][0]]+1; if(t==x) return r; else if(t>x) return Get_Kth(ch[r][0],x); else return Get_Kth(ch[r][1],x-t); } void ADD(int l,int r,int v) { Splay(Get_Kth(root,l),0); Splay(Get_Kth(root,r+2),root); Update_Add(Key_value,v); Push_Up(ch[root][1]); Push_Up(root); } LL Query(int l,int r) { Splay(Get_Kth(root,l),0); Splay(Get_Kth(root,r+2),root); return sum[Key_value]; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { Init(); char op[20]; while(m--) { scanf("%s",op); int a,b,c; if(op[0]=='Q') { scanf("%d%d",&a,&b); printf("%I64d\n",Query(a,b)); } else if(op[0]=='C') { scanf("%d%d%d",&a,&b,&c); ADD(a,b,c); } } } return 0; }