• [ACM_数据结构] 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:
    ",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
    ",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:
    ",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
    ",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 }
  • 相关阅读:
    Action常见注解的运用
    发现越来越喜欢来博客园了,所以自己也注册了一个!
    jsf 繁体教程下载pdf
    poj3210
    poj3224
    poj3219
    poj3233
    poj3372
    Paper Pal:一个中英文论文及其代码大数据搜索平台
    年轻就该多尝试,教你20小时Get一项新技能
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3700115.html
Copyright © 2020-2023  润新知