首页 > 代码库 > [HDU 1166 敌兵布阵] 线段树 或 树状数组
[HDU 1166 敌兵布阵] 线段树 或 树状数组
1 #include<iostream> 2 #include<cstdio> 3 #include<memory.h> 4 using namespace std; 5 int n,C[50005]; 6 //-------------------------- 7 int lowbit(int x){ 8 return x&-x; 9 } 10 int sum(int x){ 11 int ret=0; 12 while(x>0){ 13 ret+=C[x]; 14 x-=lowbit(x); 15 } 16 return ret; 17 } 18 void add(int x,int d){ 19 while(x<=n){ 20 C[x]+=d; 21 x+=lowbit(x); 22 } 23 } 24 //-------------------------- 25 int main(){ 26 int T; 27 scanf("%d",&T); 28 int kases=1; 29 int i,j; 30 int a; 31 for(;kases<=T;kases++){ 32 memset(C,0,sizeof(C)); 33 scanf("%d",&n); 34 for(i=1;i<=n;i++){ 35 scanf("%d",&a); 36 add(i,a); 37 } 38 char str[10]; 39 printf("Case %d:\n",kases); 40 bool ok=1; 41 while(ok){ 42 scanf("%s",str); 43 switch(str[0]){ 44 case ‘Q‘: 45 scanf("%d%d",&i,&j); 46 printf("%d\n",sum(j)-sum(i-1)); 47 break; 48 case ‘A‘: 49 scanf("%d%d",&i,&j); 50 add(i,j); 51 break; 52 case ‘S‘: 53 scanf("%d%d",&i,&j); 54 add(i,-j); 55 break; 56 case ‘E‘: 57 ok=0; 58 break; 59 default:break; 60 } 61 } 62 }return 0; 63 }
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 #define maxn 100005 5 class Node{ 6 public: 7 int l,r; 8 int add;//附加值 9 int sum; 10 }node[maxn]; 11 int getRight(int n){//获得满足2^x>=n的最小x[从0层开始,给编号获得层数] 12 return ceil(log10(n*1.0)/log10(2.0)); 13 } 14 void build(int l,int r,int num){//输入区间[1,2^getRight(n)],num=1建树 15 if(l==r){ 16 node[num].l=node[num].r=l;node[num].add=0;node[num].sum=0; 17 return; 18 } 19 node[num].l=l;node[num].r=r;node[num].add=0;node[num].sum=0; 20 build(l,(l+r)/2,num*2); 21 build((l+r)/2+1,r,num*2+1); 22 } 23 void add(int o,int l,int r,int v){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]全部加v 24 if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界] 25 node[o].add+=v; 26 }else{ 27 int M=node[o].l+(node[o].r-node[o].l)/2; 28 if(r<=M)add(o*2,l,r,v); 29 else if(l>M)add(o*2+1,l,r,v); 30 else{ 31 add(o*2,l,M,v); 32 add(o*2+1,M+1,r,v); 33 } 34 } 35 //维护节点o 36 if(node[o].l!=node[o].r){//如果区间只是一个元素就不算 37 node[o].sum=node[2*o].sum+node[2*o+1].sum; 38 }else node[o].sum=0; 39 node[o].sum+=node[o].add*(node[o].r-node[o].l+1); 40 } 41 42 //这里addadd是从上往下这条路的累计addadd值[一同回溯记录这条路节点所有add之和,减少了一次回溯累加add值] 43 //初始时直接令其为0 44 int sum=0; 45 void ask(int o,int l,int r,int addadd){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]的和 46 if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界] 47 sum+=(node[o].sum+addadd*(node[o].r-node[o].l+1)); 48 }else{ 49 int M=node[o].l+(node[o].r-node[o].l)/2; 50 if(r<=M)ask(o*2,l,r,node[o].add+addadd); 51 else if(l>M)ask(o*2+1,l,r,node[o].add+addadd); 52 else{ 53 ask(o*2,l,M,node[o].add+addadd); 54 ask(o*2+1,M+1,r,node[o].add+addadd); 55 } 56 } 57 } 58 int main(){ 59 int T; 60 scanf("%d",&T); 61 int kases=1; 62 int i,j; 63 int a; 64 for(;kases<=T;kases++){ 65 int N; 66 scanf("%d",&N); 67 build(1,1<<getRight(N),1); 68 for(i=1;i<=N;i++){ 69 scanf("%d",&a); 70 add(1,i,i,a); 71 } 72 char str[10]; 73 printf("Case %d:\n",kases); 74 bool ok=1; 75 while(ok){ 76 scanf("%s",str); 77 switch(str[0]){ 78 case ‘Q‘: 79 scanf("%d%d",&i,&j); 80 sum=0; 81 ask(1,i,j,0); 82 printf("%d\n",sum); 83 break; 84 case ‘A‘: 85 scanf("%d%d",&i,&j); 86 add(1,i,i,j); 87 break; 88 case ‘S‘: 89 scanf("%d%d",&i,&j); 90 add(1,i,i,-j); 91 break; 92 case ‘E‘: 93 ok=0; 94 break; 95 default:break; 96 } 97 } 98 }return 0; 99 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。