hdu 1892 See you 二维树状数组,很好的一道题


  1. 题目给定4种操作:  S x1 y1 x2 y2 询问以(x1 , y1) - (x2 , y2)为对角线的矩形的面积,但是这个对角线不一定是正对角线。A x1 y1 n 把点(x1 , y1)加上n。D x1 y1 n点(x1 , y1)减去n如果不足n就全部删除即可。M x1 y1 x2 y2 n 把点(x1 , y1)点值中扣除n加到(x2 , y2),如果不过n则把(x1 , y1)值全部加到(x2 , y2)
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<iostream>  
  5. #include<algorithm>  
  6. using namespace std;  
  7.   
  8. const int MAXN = 1e3+10;  
  9.   
  10. int n;  
  11. int num[MAXN][MAXN];  
  12. int treeNum[MAXN][MAXN];  
  13.   
  14. int lowbit(int x){  
  15.     return x&(-x);  
  16. }  
  17.   
  18. int getSum(int x , int y){  
  19.     int sum = 0;  
  20.     for(int i = x ; i > 0 ; i -= lowbit(i))   
  21.         for(int j = y ; j > 0 ; j -= lowbit(j))   
  22.             sum += treeNum[i][j];  
  23.     return sum;  
  24. }  
  25.   
  26. void add(int x , int y , int val){  
  27.     for(int i = x ; i < MAXN ; i += lowbit(i))   
  28.         for(int j = y ; j < MAXN ; j += lowbit(j))   
  29.             treeNum[i][j] += val;  
  30. }  
  31.   
  32. void init(){  
  33.     memset(treeNum , 0 , sizeof(treeNum));  
  34.     for(int i = 1 ; i < MAXN ; i++){  
  35.        for(int j = 1 ; j < MAXN ; j++){  
  36.            num[i][j] = 1;  
  37.            treeNum[i][j] = lowbit(i)*lowbit(j);  
  38.        }  
  39.     }  
  40. }  
  41.   
  42. void solve(){  
  43.     init();  
  44.     char c;  
  45.     int x , y , val;  
  46.     int x1 , y1 , x2 , y2;  
  47.     int x3 , y3 , x4 , y4;  
  48.     while(n--){  
  49.         scanf("%c" , &c);   
  50.         if(c == 'S'){  
  51.             scanf("%d%d" , &x1 , &y1);   
  52.             scanf("%d%d%*c" , &x2 , &y2);   
  53.             x1++ , y1++ , x2++ , y2++;  
  54.   
  55.             x3 = min(x1 , x2) , y3 = min(y1 , y2);  
  56.             x4 = max(x1 , x2) , y4 = max(y1 , y2);  
  57.             int ans = getSum(x4 , y4);   
  58.             ans -= getSum(x3-1 , y4);  
  59.             ans -= getSum(x4 , y3-1);  
  60.             ans += getSum(x3-1 , y3-1);  
  61.             printf("%d\n" , ans);  
  62.         }  
  63.         else if(c == 'A'){  
  64.             scanf("%d%d%d%*c" , &x , &y , &val);   
  65.             x++ , y++;  
  66.             num[x][y] += val;  
  67.             add(x , y , val);  
  68.         }  
  69.         else if(c == 'D'){  
  70.             scanf("%d%d%d%*c" , &x , &y , &val);   
  71.             x++ , y++;  
  72.             val = min(num[x][y] , val);  
  73.             num[x][y] -= val;  
  74.             add(x , y , -val);  
  75.         }  
  76.         else{  
  77.             scanf("%d%d" , &x1 , &y1);   
  78.             scanf("%d%d%d%*c" , &x2 , &y2 , &val);   
  79.             x1++ , y1++ , x2++ , y2++;  
  80.             val = min(num[x1][y1] , val);  
  81.             num[x1][y1] -= val;  
  82.             num[x2][y2] += val;  
  83.             add(x1 , y1 , -val);  
  84.             add(x2 , y2 , val);  
  85.         }  
  86.     }  
  87. }  
  88.   
  89. int main(){  
  90.     int cas;  
  91.     int Case = 1;  
  92.     scanf("%d" , &cas);  
  93.     while(cas--){  
  94.         scanf("%d%*c" , &n);       
  95.         printf("Case %d:\n" , Case++);  
  96.         solve();  
  97.     }  
  98.     return 0;  
  99. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值