线段树水题刷刷,生活没有希望
最近看到代码跟树状数组差不多短的非递归线段树,常数也很小——zkw线段树
于是拿道水题练练手
短到让人身无可恋
1 void add(int pos,int x){ for(pos+=M+1;pos;pos/=2) a[pos]+=x;} 2 int que(int l,int r){ for(l+=M,r+=M+2,ans=0;l^r^1;l>>=1,r>>=1)ans+=((l&1)?0:a[l|1])+((r&1)?a[r-1]:0);return ans;}
单点修改和区间查询(通过前缀和可以变成区间修改单点查询,再加特技标记可以变成区间修区间查)
1 M=1;n+=2; 2 while(M<n) 3 M*=2; 4 M--; 5 for(int i=1;i<=M+n+1;i++) 6 a[i]=0;
初始化(赋初值0是因为这道题多组数据,不然还不用)
1 #include <cstdio> 2 int t,n,M,p,l,r,ans,a[131073];char ch; 3 void add(int pos,int x){ for(pos+=M+1;pos;pos/=2) a[pos]+=x;} 4 int que(int l,int r){ for(l+=M,r+=M+2,ans=0;l^r^1;l>>=1,r>>=1)ans+=((l&1)?0:a[l|1])+((r&1)?a[r-1]:0);return ans;} 5 int main() 6 { 7 scanf("%d",&t); 8 for(int T=1;T<=t;T++) 9 { 10 printf("Case %d: ",T); 11 scanf("%d",&n); 12 M=1;n+=2; 13 while(M<n) 14 M*=2; 15 M--; 16 for(int i=1;i<=M+n+1;i++) 17 a[i]=0; 18 for(int i=1;i<=n;i++) 19 scanf("%d",&p),add(i,p); 20 for(ch=getchar();ch!='E' && ch!='Q' && ch!='A' && ch!='S';ch=getchar()); 21 while(ch!='E') 22 { 23 switch(ch) 24 { 25 case'Q': 26 getchar();getchar();getchar();getchar(); 27 scanf("%d%d",&l,&r);printf("%d ",que(l,r)); 28 break; 29 case 'A': 30 getchar();getchar(); 31 scanf("%d%d",&l,&r);add(l,r); 32 break; 33 case 'S': 34 getchar();getchar(); 35 scanf("%d%d",&l,&r);add(l,-r); 36 break; 37 } 38 for(ch=getchar();ch!='E' && ch!='Q' && ch!='A' && ch!='S';ch=getchar()); 39 } 40 getchar();getchar(); 41 } 42 return 0; 43 }
这道水题理论上不需要常数那么小,但是代码短所以还是这么打了
主程序基本都是在输入输出,,,