BZOJ2674 Attack

题意

题目链接
简洁版:平面上有\(n\)个点,每个点有一个权值,有\(m\)个操作

  • 交换两点的权值
  • 询问一个矩形区域内第\(k\)小的权值

\(n<=60000,m<=10000\)

思路

如果不是一个平面,而是一个序列,那就是一个动态区间第K大的问题,用整体二分即可解决
于是我们在这道题上线套一个整体二分,然后问题转化为如何支持高速修改与查询一个矩形区域中点的个数
不难想到用树套树进行解决。在这里我第一维(x坐标)采用的是线段树,第二维(y坐标)采用的是SBT
(当然,大多数大佬使用的线段树套树状数组当然更为简单)
时间复杂度\(O(nlog^3n)\)
另外不要忘了离散化

注意事项

  • 数组大小一定要好好计算,稍不注意就会爆
  • 清空树套树与平常的不太相同,我是把线段树每一节点对应的SBT根给清掉

code(有点长)

#include<bits/stdc++.h>
using namespace std;
const int N=60005;
const int M=10005;
int n,m,cnt,t1,t2,mn=1e9,mx,hh;
int tmp,val[N],ans[M];
struct node{int _x1,_y1,_x2,_y2,z,id,k,tp;}a[N+(M<<2)],q1[N+(M<<2)],q2[N+(M<<2)];
struct lsh{int nm,id,as;}xx[N+(M<<1)],yy[N+(M<<1)];
inline int read()
{
    int s=0,w=1; char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return s*w;
}
inline bool cmp(lsh x,lsh y){return x.nm<y.nm;}
inline bool cmp1(lsh x,lsh y){return x.id<y.id;}
inline void pre()
{
    sort(xx+1,xx+tmp+1,cmp);
    sort(yy+1,yy+tmp+1,cmp);
    for(int i=1;i<=tmp;++i)
    {
        if(i==1||xx[i].nm!=xx[i-1].nm) xx[i].as=++t1;
        else xx[i].as=t1;
        if(i==1||yy[i].nm!=yy[i-1].nm) yy[i].as=++t2;
        else yy[i].as=t2;
    }
    sort(xx+1,xx+tmp+1,cmp1);
    sort(yy+1,yy+tmp+1,cmp1);
    for(int i=1;i<=n;++i)a[i]._x1=xx[i].as,a[i]._y1=yy[i].as;
    for(int i=n+1,j=n+1;i<=cnt;++i)
        if(!a[i].tp)
        {
            a[i]._x1=xx[j].as,a[i]._y1=yy[j++].as;
            a[i]._x2=xx[j].as,a[i]._y2=yy[j++].as;
        }
        else
        {
            for(int e=i;e<=i+3;++e)
                a[e]._x1=a[a[e].id]._x1,a[e]._y1=a[a[e].id]._y1;
            ++i,++i,++i;
        }
}
struct SBT{
    int rt[(N+M<<1)<<2],siz[N<<4],rp[N<<4],tot=0;
    int lc[N<<4],rc[N<<4],rsiz[N<<4],vv[N<<4];
    const double alpha=0.55;
    inline int new_node(int v)
    {
        int num=++tot;lc[num]=rc[num]=0;
        siz[num]=rsiz[num]=rp[num]=1;vv[num]=v;//新建节点必须初始化
        return num;
    }
    inline void upt(int x)
    {
        siz[x]=siz[lc[x]]+siz[rc[x]]+rp[x];
        rsiz[x]=rsiz[lc[x]]+rsiz[rc[x]]+1;
    }
    inline void zig(int &u)
    {
        int v=lc[u];lc[u]=rc[v];rc[v]=u;
        upt(u);upt(v);u=v;
    }
    inline void zag(int &u)
    {
        int v=rc[u];rc[u]=lc[v];lc[v]=u;
        upt(u);upt(v);u=v;
    }
    void ins(int &now,int p)
    {
        if(!now){now=new_node(p);return;}
        ++siz[now];
        if(p==vv[now])++rp[now];
        else if(p<vv[now])
        {
            ins(lc[now],p);
            if(rsiz[lc[now]]>rsiz[now]*alpha) zig(now);
        }
        else
        {
            ins(rc[now],p);
            if(rsiz[rc[now]]>rsiz[now]*alpha) zag(now);
        }
        upt(now);
    }
    void del(int &now,int p)
    {
        if(!now) return;
        if(vv[now]==p)
        {
            if(rp[now]>1) --rp[now],--siz[now];
            else if(!lc[now]||!rc[now]) now=lc[now]|rc[now];
            else if(rsiz[lc[now]]>rsiz[rc[now]]) zig(now),del(now,p);
            else zag(now),del(now,p);
            if(now) upt(now);
            return;
        }
        if(p<vv[now]) del(lc[now],p);
        else del(rc[now],p);
        upt(now);
    }
    int rank(int now,int p)
    {
        if(!now) return 0;
        if(vv[now]==p) return siz[lc[now]]+rp[now];
        else if(p<vv[now]) return rank(lc[now],p);
        else return rank(rc[now],p)+siz[lc[now]]+rp[now];
    }
    inline int range(int now,int l,int r){return rank(now,r)-rank(now,l-1);}
}sbt;
struct Seg_tree{
    void update(int rt,int l,int r,int p1,int p2,int v)
    {
        if(v>0)sbt.ins(sbt.rt[rt],p2);
        else sbt.del(sbt.rt[rt],p2);
        if(l>=r) return;
        int mid=l+r>>1;
        if(p1<=mid) update(rt<<1,l,mid,p1,p2,v);
        else update(rt<<1|1,mid+1,r,p1,p2,v);
    }
    int query(int rt,int l,int r,int px1,int py1,int px2,int py2)
    {
        if(px1<=l&&r<=px2) return sbt.range(sbt.rt[rt],py1,py2);
        int mid=l+r>>1,anss=0;
        if(px1<=mid) anss+=query(rt<<1,l,mid,px1,py1,px2,py2);
        if(mid<px2) anss+=query(rt<<1|1,mid+1,r,px1,py1,px2,py2);
        return anss;
    }
    void clean(int rt,int l,int r,int p)
    {
        sbt.rt[rt]=0;
        if(l>=r)return;
        int mid=l+r>>1;
        if(p<=mid) clean(rt<<1,l,mid,p);
        else clean(rt<<1|1,mid+1,r,p);
    }
}T;
void solve(int L,int R,int l,int r)
{
    if(l>r) return;
    if(L==R)
    {
        for(int i=l;i<=r;++i)
            if(!a[i].tp) ans[a[i].id]=L;
        return;
    }
    int mid=L+R>>1,cnt1=0,cnt2=0;
    for(int i=l;i<=r;++i)
    {
        if(a[i].tp)
        {
            if(a[i].z<=mid) T.update(1,1,t1,a[i]._x1,a[i]._y1,a[i].k),q1[++cnt1]=a[i];
            else q2[++cnt2]=a[i];
        }
        else
        {
            int xk=T.query(1,1,t1,a[i]._x1,a[i]._y1,a[i]._x2,a[i]._y2);
            if(a[i].k<=xk) q1[++cnt1]=a[i];
            else q2[++cnt2]=a[i],q2[cnt2].k-=xk;
        }
    }
    sbt.tot=0;
    for(int i=l;i<=r;++i)
        if(a[i].tp&&a[i].z<=mid) T.clean(1,1,t1,a[i]._x1);
    for(int i=l;i<=l+cnt1-1;++i)a[i]=q1[i-l+1];
    for(int i=l+cnt1;i<=r;++i)a[i]=q2[i-l-cnt1+1];
    solve(L,mid,l,l+cnt1-1);
    solve(mid+1,R,l+cnt1,r);
}
int main()
{
    n=read(),m=read();cnt=n;
    for(int i=1;i<=n;++i)
    {
        int xi=read(),yi=read(),zi=read();
        a[i]=node{xi,yi,0,0,zi,i,1,1};
        xx[++tmp]=lsh{xi,i},yy[tmp]=lsh{yi,i};val[i]=zi;
        mx=max(mx,zi),mn=min(mn,zi);
    }
    char opt[10];
    for(int i=1;i<=m;++i)
    {
        scanf("%s",opt);
        if(opt[0]=='Q')
        {
            int xx1=read(),yy1=read(),xx2=read(),yy2=read(),kk=read();
            if(xx1>xx2) swap(xx1,xx2);
            if(yy1>yy2) swap(yy1,yy2);
            a[++cnt]=node{xx1,yy1,xx2,yy2,0,++hh,kk,0};
            xx[++tmp]=lsh{xx1,tmp},yy[tmp]=lsh{yy1,tmp};
            xx[++tmp]=lsh{xx2,tmp},yy[tmp]=lsh{yy2,tmp};
        }
        else
        {
            int _x=read()+1,_y=read()+1;
            if(_x==_y) continue;
            a[++cnt]=node{a[_x]._x1,a[_x]._y1,0,0,val[_x],_x,-1,1};
            a[++cnt]=node{a[_x]._x1,a[_x]._y1,0,0,val[_y],_x,1,1};
            a[++cnt]=node{a[_y]._x1,a[_y]._y1,0,0,val[_y],_y,-1,1};
            a[++cnt]=node{a[_y]._x1,a[_y]._y1,0,0,val[_x],_y,1,1};
            swap(val[_x],val[_y]);
        }
    }
    while(a[cnt].tp==1) --cnt;
    pre();
    solve(mn,mx+1,1,cnt);
    for(int i=1;i<=hh;++i)
    {
        if(ans[i]>mx) puts("It doesn't exist.");
        else printf("%d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zmyzmy/p/12127809.html
今日推荐