4 1 1 1 1 14 2 1 2 2 2 3 2 4 1 2 3 1 2 2 1 2 2 2 3 2 4 1 1 4 2 1 2 1 2 2 2 3 2 4
1 1 1 1 1 3 3 1 2 3 4 1
以前解决的都是线段树整个区间更新的问题。这还是第一次解决线段树的其他应用。这题用到了线段树的分类操作。思路来源于
http://blog.csdn.net/ophunter/article/details/9455723
写的很好很详细。
只是要注意树的结点不能写成结构体了。不然内存开不下。于是只用往函数参数上打主意了。。。
虽然有点麻烦不多节约内存的效果还是立竿见影的。。
#include <iostream> #include<stdio.h> #include<string.h> using namespace std; const int N=50001; int st[55][3*N]; int low[11]= {0,0,1,3,6,10,15,21,28,36,45}; void btree(int *sbt,int l,int r,int k,int c) { int mid,ls,rs; sbt[k]=0; if(l==r) { if(c) scanf("%d",&sbt[k]); return; } ls=k<<1; rs=k<<1|1; mid=(l+r)>>1; btree(sbt,l,mid,ls,c); btree(sbt,mid+1,r,rs,c); } void update(int *sbt,int left,int right,int l,int r,int k,int d) { int mid,ls,rs; if(left==l&&right==r) { sbt[k]+=d; return; } ls=k<<1; rs=k<<1|1; mid=(left+right)>>1; if(sbt[k]) { sbt[ls]+=sbt[k]; sbt[rs]+=sbt[k]; sbt[k]=0; } if(r<=mid) update(sbt,left,mid,l,r,ls,d); else if(l>mid) update(sbt,mid+1,right,l,r,rs,d); else { update(sbt,left,mid,l,mid,ls,d); update(sbt,mid+1,right,mid+1,r,rs,d); } } int qu(int *sbt,int left,int right,int a,int k) { int mid,ls,rs; if(left==right) return sbt[k]; ls=k<<1; rs=k<<1|1; mid=(left+right)>>1; if(sbt[k]) { sbt[ls]+=sbt[k]; sbt[rs]+=sbt[k]; sbt[k]=0; } if(a>mid) return qu(sbt,mid+1,right,a,rs); else return qu(sbt,left,mid,a,ls); } int main() { int n,q,a,b,c,k,i,com,pos,sum; while(~scanf("%d",&n)) { btree(st[0],1,n,1,1); for(i=1; i<55; i++) btree(st[i],1,n,1,0); scanf("%d",&q); while(q--) { scanf("%d",&com); if(com==1) { scanf("%d%d%d%d",&a,&b,&k,&c); pos=low[k]+a%k; update(st[pos],1,n,a,b,1,c); } else { scanf("%d",&a); sum=0; for(k=1; k<=10; k++) { pos=low[k]+a%k; sum+=qu(st[pos],1,n,a,1); } printf("%d\n",sum); } } } return 0; }
用树状数组又写了下。速度快了很多。
#include <iostream> #include<stdio.h> #include<string.h> using namespace std; const int N=50001; int con[55][50010];//55个树状数组。思路同线段树。只是更新求和比线段树快。空间也比线段树小 int an[50010]; int low[11]= {0,0,1,3,6,10,15,21,28,36,45}; int n; int lowbit(int x) { return x&(-x); } void update(int* c,int x,int chan) { while(x>0) { c[x]+=chan; x-=lowbit(x); } } int qu(int* c,int x) { int s=0; while(x<=n) { s+=c[x]; x+=lowbit(x); } return s; } int main() { int q,a,b,c,k,i,com,pos,sum; while(~scanf("%d",&n)) { memset(con,0,sizeof con); for(i=1;i<=n;i++) scanf("%d",an+i); scanf("%d",&q); while(q--) { scanf("%d",&com); if(com==1) { scanf("%d%d%d%d",&a,&b,&k,&c); pos=low[k]+a%k; update(con[pos],b,c); update(con[pos],a-1,-c); } else { scanf("%d",&a); sum=an[a]; for(k=1; k<=10; k++) { pos=low[k]+a%k; sum+=qu(con[pos],a); } printf("%d\n",sum); } } } return 0; }