Mokia【题解】

前言

刚开始开心的二维树状数组(真裸),后面发现他在故意卡树状数组(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);
    }
}

猜你喜欢

转载自blog.csdn.net/JH_2002/article/details/81427566