C. Rooks Defenders - 树状数组

题面

分析

三种操作,1.在 ( x , y ) (x, y) (x,y)位置放置一个棋子。
2.将 ( x , y ) (x, y) (x,y)位置的棋子拿走。
3.判断 ( x 1 , y 1 ) (x1, y1) (x1,y1)为左上角, ( x 2 , y 2 ) (x2, y2) (x2,y2)为右下角的矩形是否被棋子攻击。
这里有个误区就是棋子攻击一个格子要么横坐标相等要么纵坐标相等,或者棋子和格子在同一位置,所有矩形被攻击是指他的每一行都有被攻击的棋子,或者他的每一列都有被攻击的棋子,可以树状数组进行加减操作以及查询和。

代码
#include 

#define int long long

using namespace std;

const int N = 1e5 + 10;

int n;
int col[N];
int row[N];

struct node {
    int c[N];
    void add(int x, int k) {
        for(int i = x; i <= n; i += i & -i) c[i] += k;
    }
    int getsum(int x) {
        int sum = 0;
        for(int i = x; i >= 1; i -= i & -i) sum += c[i];
        return sum;
    }
}a, b;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int q;
    cin >> n >> q;
    while(q --) {
        int t;
        cin >> t;
        if(t == 1) {
            int x, y;
            cin >> x >> y;
            if(++ row[x] == 1) a.add(x, 1);
            if(++ col[y] == 1) b.add(y, 1);
        }
        else if(t == 2) {
            int x, y;
            cin >> x >> y;
            if(-- row[x] == 0) a.add(x, -1);
            if(-- col[y] == 0) b.add(y, -1);
        }
        else if(t == 3) {
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            if(a.getsum(x2) - a.getsum(x1 - 1) == x2 - x1 + 1 || b.getsum(y2) - b.getsum(y1 - 1) == y2 - y1 + 1) cout << "Yes\n";
            else cout << "No\n";
        }
    }
}

你可能感兴趣的:(算法,c++,树状数组)