[ifrog 1069 Rectangle Cover] 二维树状数组

[ifrog 1069 Rectangle Cover] 二维树状数组

知识点:tree 2-D Binary Indexed Tree

1. 题目链接

[ifrog 1069 Rectangle Cover]

2. 题意描述

有一个 nn 的区域,在这个区域进行两种操作,总共操作 q 次。

  • 操作一: 以(x1,y1)为左上点, (x2,y2) 为右下点,画一个矩形;

    • 操作二:求点 (x,y) 上有多少个矩形覆盖。
    • 数据范围: 1n103,q50000

      3. 解题思路

      赤裸裸的二维树状数组。区间覆盖的时候需要维护四个点: (x1,y1),(x2+1,y1),(x1,y2+1),(x2+1,y2+1)

      4. 实现代码

      #include <bits/stdc++.h>
      using namespace std;
      
      typedef long long LL;
      typedef pair<int, int> PII;
      typedef pair<LL, LL> PLL;
      
      const int MAXN = 1000 + 5;
      const int INF = 0x3f3f3f3f;
      const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
      
      int n, q;
      LL c[MAXN][MAXN];
      
      inline int lowbit(const int& x) { return x & (-x); }
      
      void add(int x, int yz, int v) {
          while(x <= n) {
              int y = yz;
              while(y <= n) {
                  c[x][y] += v;
                  y += lowbit(y);
              }
              x += lowbit(x);
          }
      }
      
      LL query(int x, int yz) {
          LL ret = 0;
          while(x > 0) {
              int y = yz;
              while(y > 0) {
                  ret += c[x][y];
                  y -= lowbit(y);
              }
              x -= lowbit(x);
          }
          return ret;
      }
      int main() {
      #ifdef ___LOCAL_WONZY___
          freopen("input.txt", "r", stdin);
      #endif // ___LOCAL_WONZY___
          int _, cas = 0;
          scanf("%d", &_);
          char op[5];
          int x[3], y[3];
          while(_ --) {
              if(cas) printf("\n");
              ++ cas;
              memset(c, 0, sizeof(c));
              scanf("%d %d", &n, &q);
              while(q --) {
                  scanf("%s", op);
                  if(op[0] == 'Q') {
                      scanf("%d %d", x, y);
                      printf("%lld\n", query(x[0], y[0]));
                  } else {
                      scanf("%d %d %d %d", x + 1, y + 1, x + 2, y + 2);
                      add(x[1], y[1], 1);
                      add(x[2] + 1, y[2] + 1, 1);
                      add(x[1], y[2] + 1, -1);
                      add(x[2] + 1, y[1], -1);
                  }
              }
          }
          return 0;
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值