前言
刚开始开心的二维树状数组(真裸),后面发现他在故意卡树状数组(W有200w)离散化都不行.
所以~~开心~~CDQ。
题面
戳一下就好了。
吐槽
特意上网搜了一下mokia,发现是盗版nokia。这年头,洛基亚还有盗版,盗版比正版还火,都用来出题
sol
CDQ除了能用来解决N维偏序以外,好像就没什么了,所以转换成三位偏序就好了。
具体来说就是,对于加人这种操作,记一下加的位置,加的大小。注意到CDQ一般离线,所以再记一个时间。然后询问就只要拆成四个坐标,容斥的加加减减。然后在记一个时间。只要查询x,y,time都小于等于自己的有多少个就可以了。
各种变量之间的链接一开始就要想好,要不然到时候还要花时间去找对自己贡献答案的数据在哪.
code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline char gc(){
static char buf[1<<4],*p1=buf,*p2=buf;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<4,stdin),p1==p2)?EOF:*p1++;
}
template <class T>
inline void read(T&data){
register char ch=0;data=0;
while(ch<'0'||ch>'9')ch=gc();
while(ch<='9'&&ch>='0'){
data=(data<<3)+(data<<1)+(ch^48);
ch=gc();
}
return;
}
const int _ = 5e5;
struct node{
int x,y,t,zh,num,ki;
LL ans;
}s[_],zjy[_];
struct Que{
int x1,x2,y1,y2;
int b[5];
}qq[int(2e5)];
LL tree[_];
int cnt,w,nn,MX;
struct Pair{
int e,r;
}Q[_];
bool cmp(const node x,const node y){
if(x.x!=y.x)return x.x<y.x;
if(x.y!=y.y) return x.y<y.y;
return x.t<y.t;
}
inline int lowbit(register int k){return k&(-k);}
inline void modify(register int loc,register int zh){
for(register int i=loc;i<=MX;i+=lowbit(i))tree[i]+=zh;
}
inline LL query(register int loc){
LL ret=0;
for(register int i=loc;i;i-=lowbit(i))ret+=tree[i];return ret;
}
void CDQ(register int L,register int R){
if(L==R)return;
register int mid = (L+R)>>1;
CDQ(L,mid);CDQ(mid+1,R);
register int pin1=L,pin2=mid+1,ppl=L,cc=0;
for(;pin2<=R;++pin2){
while(pin1<=mid&&s[pin2].y>=s[pin1].y){
zjy[ppl]=s[pin1];
if(s[pin1].num==0){
modify(s[pin1].t,s[pin1].zh);
Q[++cc]=(Pair){s[pin1].t,s[pin1].zh};
}
++ppl,++pin1;
}
if(s[pin2].num)s[pin2].ans+=query(s[pin2].t);
zjy[ppl]=s[pin2];++ppl;
}
while(pin1<=mid){
zjy[ppl]=s[pin1];++ppl;
++pin1;
}
for(register int i=L;i<=R;++i)
s[i]=zjy[i];
for(register int i=1;i<=cc;++i)
modify(Q[i].e,-Q[i].r);
return;
}
int main(){
read(w);read(w);int qcnt=0;
register int a,b,c,d,e,tim2=0;
do{
read(a);
if(a==1){
read(b),read(c),read(d);
s[++cnt].x=b,s[cnt].y=c,s[cnt].t=++tim2,s[cnt].zh=d;
continue;
}
if(a==2){
read(b),read(c),read(d),read(e);
qq[++qcnt].x1=b,qq[qcnt].y1=c,qq[qcnt].x2=d,qq[cnt].y2=e;
s[++cnt].x=b-1,s[cnt].y=c-1,s[cnt].num=qcnt,s[cnt].ki=1,s[cnt].t=++tim2;
s[++cnt].x=b-1,s[cnt].y=e,s[cnt].num=qcnt,s[cnt].ki=2,s[cnt].t=tim2;
s[++cnt].x=d,s[cnt].y=c-1,s[cnt].num=qcnt,s[cnt].ki=3,s[cnt].t=tim2;
s[++cnt].x=d,s[cnt].y=e,s[cnt].num=qcnt,s[cnt].ki=4,s[cnt].t=tim2;
continue;
}
if(a==3)break;
}while(1);
MX=tim2;
sort(s+1,s+cnt+1,cmp);
nn=cnt;
for(register int i=1;i<=cnt;++i){
if(s[i].num)
qq[s[i].num].b[s[i].ki]=i;
}
CDQ(1,nn);
sort(s+1,s+nn+1,cmp);
for(register int i=1;i<=qcnt;++i){
register LL ans=s[qq[i].b[1]].ans+s[qq[i].b[4]].ans-s[qq[i].b[2]].ans-s[qq[i].b[3]].ans;
printf("%lld\n",ans);
}
}