【KD树】 BZOJ5223 [Lydsy2017省队十连测] 有理有据题

版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/89090760

【题目】
BZOJ
简化题意:
数轴上有 n n 个炸弹可以表示为 [ a i , b i ] [a_i,b_i] ,同时有 m m 个建筑(标号 1 m 1\sim m )可以表示为 [ l i , r i ] [l_i,r_i] ,若一个炸弹与一个建筑所表示的线段有交则炸弹可以炸毁这个建筑。支持三种操作:

  • 加入一个建筑,按顺序标号
  • 查询第 i i 个炸弹能炸毁的标号连续的房子最多多少个
  • 查询所有炸弹第二个操作答案的异或和(保证这种操作很少)

n , m 5 × 1 0 4 n,m\leq 5\times 10^4 ,操作 1 , 2 2 × 1 0 5 1,2\leq 2\times 10^5 ,操作 3 20 3\leq 20 ,坐标范围 4 × 1 0 5 \leq 4\times 10^5

【解题思路】
两个线段 [ l i , r i ] , [ l j , r j ] [l_i,r_i],[l_j,r_j] 相交,当且仅当 l i r j , l j r i l_i\leq r_j,l_j\leq r_i

观察到没有增加炸弹的操作,不妨将炸弹表示为二维平面上一个点 ( a i , b i ) (a_i,b_i) ,建筑表示为二维平面上一个矩形,横坐标覆盖 [ 1 , r i ] [1,r_i] ,纵坐标覆盖 [ l i , N ] [l_i,N] ,其中 N N 是一个极大值,这里取 4 × 1 0 5 4\times 10^5 。那么所有能炸毁这个建筑的炸弹均被这个矩形覆盖,不能的不被覆盖。

这样看增加操作,相当于能被矩形覆盖的区域 + 1 +1 ,不能的置 0 0 ,询问就是单点历史最大值。

写过线段树经典题的我一点也不虚这个标记。

复杂度大概可以用 O ( Q N ) O(Q\sqrt N) 来表示吧。

标记实现看了别人代码,然后跑不过去。

卡常看了别人代码,然后还是跑不过去。

【参考代码】

#include<bits/stdc++.h>
using namespace std;
 
const int N=5e4+100,MX=400000,inf=0x3f3f3f3f;
int pcnt,rem;
 
namespace IO
{
    const int LEN=100000;
    struct IO
    {
        char ibuf[LEN],obuf[LEN],*ih,*oh,*lastin,*lastout;
        IO(){ih=ibuf+LEN,oh=obuf,lastin=ibuf+LEN,lastout=obuf+LEN-1;}
        inline char getchar(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,LEN,stdin),ih==lastin)?EOF:*ih++;}
        inline void putchar(char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}
        inline int read()
        {
            int ret=0,f=1;char c=getchar();
            while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
            while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
            return f?ret:-ret;
        }
        inline void reads(char *s)
        {
            char c=getchar();
            while(!isalpha(c)) c=getchar();
            while(isalpha(c)) *s++=c,c=getchar();
            *s++='\0';
        }
        inline void write(int x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10^48);}
        inline void writesp(int x){write(x);putchar(' ');}
        inline void writeln(int x){write(x);putchar('\n');}
        inline void writes(char *s){while(isalpha(*s))putchar(*s++);}
        ~IO(){fwrite(obuf,1,oh-obuf,stdout);}
    }I;
}
using namespace IO;
 
namespace Data_Structure
{
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
    struct tag
    {
        int x,y;
        inline tag(int _x=0,int _y=-inf):x(_x),y(_y){}
        inline friend tag gmax(const tag&a,const tag&b){return tag(Max(a.x,b.x),Max(a.y,b.y));}
        inline friend tag merge(const tag&a,const tag&b){return tag(Max(-inf,a.x+b.x),Max(a.y+b.x,b.y));}
        inline friend bool equal(const tag&a,const tag&b){return a.x==b.x && a.y==b.y;}
    };
    struct coor
    {
        int x,y;
        inline coor(int _x=0,int _y=0):x(_x),y(_y){}
        inline friend coor gmax(const coor&a,const coor&b){return coor(Max(a.x,b.x),Max(a.y,b.y));}
        inline friend coor gmin(const coor&a,const coor&b){return coor(Min(a.x,b.x),Min(a.y,b.y));}
    }a[N],b[N];
    inline bool cmpx(const coor&a,const coor&b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
    inline bool cmpy(const coor&a,const coor&b){return a.y<b.y || (a.y==b.y && a.x<b.x);}
    struct node
    {
        coor mx,mi,p;
        tag htag,ntag;
        int lc,rc,nmx,hmx;
    };
    struct KDT
    {
        #define ls t[x].lc
        #define rs t[x].rc
        #define sqr(x) ((x)*(x))
 
        int sz;
        node t[N];
        void build(int &x,int l,int r)
        {
            x=++sz;int mid=(l+r)>>1;
            double avex=0,avey=0,sumx=0,sumy=0;
            for(int i=l;i<=r;++i) avex+=b[i].x, avey+=b[i].y;
            avex/=(r-l+1); avey/=(r-l+1);
            for(int i=l;i<=r;++i) sumx+=sqr(b[i].x-avex), sumy+=sqr(b[i].y-avey);
            if(sumx>sumy) nth_element(b+l,b+mid,b+r+1,cmpx);
            else nth_element(b+l,b+mid,b+r+1,cmpy);
            //nth_element(b+l,b+mid,b+r+1,D?cmpx:cmpy);
            t[x].p=t[x].mx=t[x].mi=b[mid];
            if(l<mid)
            {
                build(ls,l,mid-1);
                t[x].mx=gmax(t[x].mx,t[ls].mx);t[x].mi=gmin(t[x].mi,t[ls].mi);
            }
            if(r>mid)
            {
                build(rs,mid+1,r);
                t[x].mx=gmax(t[x].mx,t[rs].mx);t[x].mi=gmin(t[x].mi,t[rs].mi);
            }
            //printf("%d %d %d %d %d %d %d\n",x,t[x].p.x,t[x].p.y,t[x].mi.x,t[x].mx.x,t[x].mi.y,t[x].mx.y);
        }
        inline int inmp(const coor&pl,const coor&pr,int l,int r,int L,int R)
        {
            if(l<=pl.x && pr.x<=r && L<=pl.y && pr.y<=R) return 1;
            if(pr.x<l || pl.x>r  || pr.y<L || pl.y>R) return -1;
            return 0;
        }
        inline void addval(int x,int va,int vc)
        {
            t[x].nmx=Max(t[x].nmx+va,vc);t[x].hmx=Max(t[x].nmx,t[x].hmx);   
        }
        inline void addtag(int x,const tag&ht,const tag&nt)
        {
            t[x].htag=gmax(t[x].htag,merge(t[x].ntag,ht));
            t[x].ntag=merge(t[x].ntag,nt);
            t[x].hmx=Max(t[x].hmx,Max(t[x].nmx+ht.x,ht.y));
            t[x].nmx=Max(t[x].nmx+nt.x,nt.y);
        }
        inline void pushdown(int x)
        {
            if(equal(t[x].htag,t[x].ntag) && equal(t[x].htag,tag())) return;
            if(ls) addtag(ls,t[x].htag,t[x].ntag);
            if(rs) addtag(rs,t[x].htag,t[x].ntag);     
            t[x].htag=t[x].ntag=tag();
        }
        void update(int x,int l,int r,int L,int R)
        {
            //if(pcnt>rem) cerr<<x<<" "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
            if(!x) return;
            pushdown(x);int v=inmp(t[x].mi,t[x].mx,l,r,L,R);
            //printf("%d %d %d %d %d %d\n",x,v,l,r,L,R);
            if(!~v){addtag(x,tag(-inf,0),tag(-inf,0));return;}
            if(v){addtag(x,tag(1,0),tag(1,0));return;}
            if(inmp(t[x].p,t[x].p,l,r,L,R)==1) addval(x,1,0);
            else addval(x,-inf,0);
            //if(pcnt>rem) cerr<<x<<" "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
            update(ls,l,r,L,R);update(rs,l,r,L,R);
        }
        int query(int x,int l,int r)
        {
            if(!x) return 0;
            pushdown(x);int v=inmp(t[x].mi,t[x].mx,l,l,r,r);
            if(!~v) return 0;
            if(t[x].p.x==l && t[x].p.y==r) return t[x].hmx;
            v=0;
            if(ls) v+=query(ls,l,r);
            if(rs) v+=query(rs,l,r);
            return v;
        }
        int queryall(int x)
        {
            pushdown(x);int v=t[x].hmx;
            if(ls) v^=queryall(ls);
            if(rs) v^=queryall(rs);
            return v;
        }
        #undef ls
        #undef rs
        #undef sqr
    }T;
#undef Max
#undef Min
}
using namespace Data_Structure;
 
namespace DreamLolita
{
    int n,m,Q,rt,x,y;
    void solution()
    {
        n=I.read();m=I.read();Q=I.read();
        for(int i=1;i<=n;++i) a[i].x=I.read(),a[i].y=I.read(),b[i]=a[i];
        T.build(rt,1,n);
        for(int i=1;i<=m;++i) x=I.read(),y=I.read(),T.update(rt,1,y,x,MX);
        while(Q--)
        {
            char op=I.getchar(); while(!isalpha(op)) op=I.getchar();
            if(op=='A') x=I.read(),y=I.read(),T.update(rt,1,y,x,MX);
            else if(op=='C') x=I.read(),I.writeln(T.query(rt,a[x].x,a[x].y));
            else I.writeln(T.queryall(rt));
        }
        //cerr<<clock();
    }
}
 
int main()
{
#ifdef Durant_Lee
    freopen("BZOJ5223.in","r",stdin);
    freopen("BZOJ5223.out","w",stdout);
#endif
    DreamLolita::solution();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_Lolita/article/details/89090760
今日推荐