用线段树维护行和列的值
单点修改,维护区间数量
#include<iostream>
#include<cstring>
#include<limits>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<cmath>
#include<map>
#include<set>
using namespace std;
#pragma GCC optimize(3)
typedef long long LL;
//#define int long long
#define endl '\n'
typedef pair<int, int>PII;
//#define x first
//#define y second
const int N = 1e5 + 10,M = N * N;
int n,m,k;
struct Node
{
int l,r;
int v,sum;//v维护的是每一行/列上的车数,sum是这个点是否有车(维护的是区间)
}tr1[N * 4],tr2[N * 4];
//维护每一行或者是列上是否有车
void pushup(Node tr[],int u)
{
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(Node tr[],int u,int l,int r)
{
tr[u] = {l,r,0,0};
if(l == r)return;
int mid = l + r >> 1;
build(tr,u << 1,l,mid),build(tr,u << 1 | 1,mid + 1,r);
pushup(tr,u);
}
void modify(Node tr[],int u,int x,int c)
{
if(tr[u].l == x && tr[u].r == x)
{
tr[u].v += c;
tr[u].sum = tr[u].v > 0;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid)modify(tr,u << 1,x,c);
if(x > mid)modify(tr,u << 1 | 1,x,c);
pushup(tr,u);
}
int query(Node tr[],int u,int l,int r)
{
if(tr[u].l >= l && tr[u].r <= r)return tr[u].sum;
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if(l <= mid)res += query(tr,u << 1,l,r);
if(r > mid)res += query(tr,u << 1 | 1,l,r);
return res;
}
//维护每一行每一列车的数量
void solve()
{
int n,m;cin >> n >> m;
build(tr1,1,1,n),build(tr2,1,1,n);
while(m --)
{
int t,x,y;cin >> t;
if(t == 1)
{
cin >> x >> y;
modify(tr1,1,x,1),modify(tr2,1,y,1);
}
else if(t == 2)
{
cin >> x >> y;
modify(tr1,1,x,-1),modify(tr2,1,y,-1);
}
else
{
int p,q;cin >> x >> y >> p >> q;
if(query(tr1,1,x,p) != p - x + 1 && query(tr2,1,y,q) != q - y + 1)
cout << "NO" << endl;
else cout << "YES" << endl;
}
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
// int t;
// cin >> t;
// while (t --) {
// solve();
// }
solve();
return 0;
}