题目背景
蕾米莉亚的红雾异变失败后,很不甘心。
题目描述
经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放。
我们将幻想乡看做是一个 n \times mn×m的方格地区,一开始没有任何一个地区被红雾遮盖。蕾米莉亚每次站在某一个地区上,向东南西北四个方向各发出一条无限长的红雾,可以影响到整行/整列,但不会影响到她所站的那个地区。如果两阵红雾碰撞,则会因为密度过大而沉降消失。灵梦察觉到了这次异变,决定去解决它。但在解决之前,灵梦想要了解一片范围红雾的密度。可以简述为两种操作:
1 x y
蕾米莉亚站在坐标 (x,y)(x,y) 的位置向四个方向释放无限长的红雾。
2 x1 y1 x2 y2
询问左上点为(x1,y1)(x1,y1),右下点为 (x2,y2)(x2,y2) 的矩形范围内,被红雾遮盖的地区的数量。
输入格式
第一行三个整数 n,m,qn,m,q,表示幻想乡大小为 n \times mn×m,有 qq 个询问。
接下来 qq 行,每行 33 个或 55 个整数,用空格隔开,含义见题目描述。
输出格式
对于每一个操作 22,输出一行一个整数,表示对应询问的答案。
输入输出样例
输入 #1复制
4 4 3 1 2 2 1 4 4 2 1 1 4 4
输出 #1复制
8
说明/提示
样例输入输出 1 解释
用o
表示没有红雾,x
表示有红雾,两次释放红雾后幻想乡地图如下:
oxox
xoxo
oxox
xoxo
数据规模与约定
- 对于 20\%20% 的数据,1 \le n,m,q \le 2001≤n,m,q≤200。
- 对于 40\%40% 的数据,1 \le n,m,q \le 10^31≤n,m,q≤103。
- 对于 100\%100% 的数据,1 \le n,m,q \le 10^51≤n,m,q≤105,1 \le x_1,x_2,x \le n1≤x1,x2,x≤n,x_1 \le x_2x1≤x2,1 \le y_1,y_2,y \le m1≤y1,y2,y≤m,y_1 \le y_2y1≤y2。
思路:对于每次添加来说,都是添加一行或者添加一列
并且(x,y)这个位置不添加,那么对于每一对x,y来说我们就多算了两个
用两个树状数组分别维护行和列
对于如果有两个的话会消失这个操作转换为每次取反
所以我们要用数组来记录每次的行或列的上一个状态是什么
如果这个数组记录是1的话就在记录x的树状数组的x的位置-1,如果是0的话就在x的位置+1
(这里需要对x和y两个坐标写不同的add 和sum函数,注意sum函数的i的范围不同,对于x是n,对于y是m )
然后再对这个数组进行取反操作
设x0是x1,x2之间状态是1 的行的数量
y0=y1,y2之间状态是1的列的数量
在求x1 y1 x2 y2之间的数量就是:
x0*(y2-y1)+y0*(x2-x1)-x0*y0*2(重复算了两次的相交的点的数量)
/*
.----------------. .----------------. .----------------. .----------------.
| .--------------. || .--------------. || .--------------. || .--------------. |
| | ________ | || | _________ | || | ____ ____ | || | ____ | |
| | |_ ___ `. | || | |_ ___ | | || ||_ \ / _|| || | .' `. | |
| | | | `. \ | || | | |_ \_| | || | | \/ | | || | / .--. \ | |
| | | | | | | || | | _| _ | || | | |\ /| | | || | | | | | | |
| | _| |___.' / | || | _| |___/ | | || | _| |_\/_| |_ | || | \ `--' / | |
| | |________.' | || | |_________| | || ||_____||_____|| || | `.____.' | |
| | | || | | || | | || | | |
| '--------------' || '--------------' || '--------------' || '--------------' |
'----------------' '----------------' '----------------' '----------------'
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<cmath>
#include<stack>
#define int long long
#define lowbit(x) x&(-x)
#define PI 3.1415926535
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll gcd(ll a,ll b) {
return b? gcd(b,a%b):a;
}
/*
int dx[8]={-2,-2,-1,1,2,2,-1,1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
int dx[8]={-1,1,0,0,-1,-1,1,1};
int dy[8]={0,0,-1,1,-1,1,-1,1};
*/
//int e[N],ne[N],h[N],idx,w[N];
/*void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
*/
const int N=2e5+10;
int m,q,n;
int tr1[N*4],tr2[4*N];
int dx[N],dy[N];
int read(){
int k=0; char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
k=k*10+c-48, c=getchar();
return k;
}
void addx(ll x,ll c){
for(ll i=x;i<=n;i+=lowbit(i))tr1[i]+=c;
}
void addy(ll x,ll c){
for(ll i=x;i<=m;i+=lowbit(i))tr2[i]+=c;
}
ll sumx(ll x){
ll res=0;
for(ll i=x;i;i-=lowbit(i))res+=tr1[i];
return res;
}
ll sumy(ll x){
ll res=0;
for(ll i=x;i;i-=lowbit(i))res+=tr2[i];
return res;
}
void sove(){
n=read();
m=read();
q=read();
while(q--){
int op;
op=read();
if(op==1){
int x,y;
x=read();
y=read();
(dx[x])?addx(x,-1):addx(x,1);
dx[x]^=1;
(dy[y])?addy(y,-1):addy(y,1);
dy[y]^=1;
}else {
int x1,y1,x2,y2;
x1=read();
y1=read();
x2=read();
y2=read();
int x0=sumx(x2)-sumx(x1-1);
int y0=sumy(y2)-sumy(y1-1);
int ans=x0*(y2-y1+1)+y0*(x2-x1+1)-x0*y0*2;
cout<<ans<<endl;
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie() ,cout.tie() ;
int t=1;
// cin>>t;
while(t--){
sove();
}
return 0;
}