• bzoj5003: 与链 5004: 开锁魔法II 5005:乒乓游戏


    www.lydsy.com/JudgeOnline/upload/task.pdf

    第一题题意可以转为选一个长度k的序列,每一项二进制的1的位置被下一项包含,且总和为1,考虑每个二进制位的出现位置,可以转化为一个多重背包求方案数的问题。

    第二题构成一些环,可以每个环直接计算,然后合并答案。

    第三题区间包含相当于单向边,区间相交不包含就是双向边,将区间相交不包含的情况缩点,剩余的单向边构成一棵树(几个被缩起来的区间可以用它们的并集表示),用lct维护树形态,查询即为询问两点是否是祖先关系,对于修改,由于区间长度递增,只有至多两种缩点情况:1.新加入的区间与某棵树的根缩点(另用平衡树维护所有根对应的区间,实际上需要再分几类);2.新加入的区间与树上非根的点缩点(另用线段树维护所有非根节点对应的区间)。

    前两题代码实现比较简单,所以这里只给出第三题的代码。

    #include<bits/stdc++.h>
    int _(){
        int x=0,f=1,c=getchar();
        while(c<48)c=='-'?f=-1:0,c=getchar();
        while(c>47)x=x*10+c-48,c=getchar();
        return x*f;
    }
    #define lc ch][0
    #define rc ch][1
    #define fa ch][2
    const int N=2e5+77,inf=0x3f3f3f3f;
    struct itv{
        int l,r,id;
        bool operator<(const itv&w)const{return l<w.l;}
    };
    struct cmpl{bool operator()(const itv&a,const itv&b){return a.l>b.l;}};
    struct cmpr{bool operator()(const itv&a,const itv&b){return a.r<b.r;}};
    std::set<itv>st;
    int n,f[N],ch[N][4],idp=0;
    int qs[N][3],xs[N],xp=0,mx=1,tl[577777],tr[577777];
    std::priority_queue<itv,std::vector<itv>,cmpl>ls[N];
    std::priority_queue<itv,std::vector<itv>,cmpr>rs[N];
    int gf(int x){
        while(x!=x[f])x=x[f]=x[f][f];
        return x;
    }
    bool nrt(int x){return x==x[fa][lc]||x==x[fa][rc];}
    int wc(int x){return x==x[fa][rc];}
    void rot(int x){
        int f=x[fa],g=f[fa],d=wc(x);
        if(nrt(f))g[ch][wc(f)]=x;
        x[fa]=g;
        (f[ch][d]=x[ch][d^1])[fa]=f;
        (x[ch][d^1]=f)[fa]=x;
    }
    void sp(int x){
        while(nrt(x)){
            int f=x[fa];
            if(nrt(f))rot(wc(x)==wc(f)?f:x);
            rot(x);
        }
    }
    int acs(int x){int y=0;for(;x;sp(x),x[rc]=y,y=x,x=x[fa]);return y;}
    void lk(int a,int b){acs(a)[fa]=b;}
    void ctlk(int a,int b){acs(a),sp(a);a[lc][fa]=0,a[lc]=0,a[fa]=b;}
    int max(int a,int b){return a>b?a:b;}
    int min(int a,int b){return a<b?a:b;}
    void tl_up(int x){
        tl[x+mx]=ls[x].size()?ls[x].top().l:inf;
        for(x=x+mx>>1;x;x>>=1)tl[x]=min(tl[x<<1],tl[(x<<1)+1]);
    }
    void tr_up(int x){
        tr[x+mx]=rs[x].size()?rs[x].top().r:-inf;
        for(x=x+mx>>1;x;x>>=1)tr[x]=max(tr[x<<1],tr[(x<<1)+1]);
    }
    int $(int x){
        return std::lower_bound(xs+1,xs+xp+1,x)-xs;
    }
    void tr_ins(itv w){
        int _l=$(w.l),_r=$(w.r);
        ls[_r].push(w),tl_up(_r);
        rs[_l].push(w),tr_up(_l);
    }
    void chk(itv w,int z){
        int p,u;
        while(tl[z]<w.l){
            for(p=z;p<mx;p<<=1,p+=tl[p]>=w.l);
            p-=mx;
            u=ls[p].top().id;
            if(u==f[u])ctlk(u,f[u]=w.id);
            ls[p].pop();
            tl_up(p);
        }
        while(tr[z]>w.r){
            for(p=z;p<mx;p<<=1,p+=tr[p]<=w.r);
            p-=mx;
            u=rs[p].top().id;
            if(u==f[u])ctlk(u,f[u]=w.id);
            rs[p].pop();
            tr_up(p);
        }
    }
    void tr_del(itv w){
        for(int l=$(w.l)+mx,r=$(w.r)+mx;r-l>1;l>>=1,r>>=1){
            if(~l&1)chk(w,l+1);
            if(r&1)chk(w,r-1);
        }
    }
    void ins(itv w){
        tr_del(w);
        std::set<itv>::iterator it=st.lower_bound(w);
        if(it!=st.end()&&it->l==w.l&&it->r>w.r)return lk(w.id,f[w.id]=it->id);
        if(it!=st.begin()&&(--it)->r>w.l){
            int u=it->id;
            if(it->r>=w.r)return lk(w.id,f[w.id]=u);
            w.l=it->l,f[u]=w.id;
            lk(u,w.id);
            st.erase(it);
        }
        while((it=st.lower_bound(w))!=st.end()&&it->l<w.r){
            int u=it->id;
            if(it->r>w.r)w.r=it->r,f[u]=w.id;
            else tr_ins(*it);
            lk(u,w.id);
            st.erase(it);
        }
        st.insert(w);
    }
    bool query(int x,int y){
        x=gf(x),y=gf(y);
        if(x==y)return 1;
        x=acs(x);
        int y0=y;
        for(;nrt(y);y=y[fa]);
        sp(y0);
        return x==y;
    }
    int main(){
        n=_();
        for(int i=1;i<=n;++i){
            qs[i][0]=_();
            qs[i][1]=_();
            qs[i][2]=_();
            if(qs[i][0]==1)xs[++xp]=qs[i][1],xs[++xp]=qs[i][2];
        }
        std::sort(xs+1,xs+xp+1);
        for(;mx<=xp+5;mx<<=1);
        for(int i=mx*2-1;i;--i)tl[i]=inf,tr[i]=-inf;
        for(int i=1;i<=n;++i){
            f[i]=i;
            int o=qs[i][0],x=qs[i][1],y=qs[i][2];
            if(o==1)ins((itv){x,y,++idp});
            else puts(query(x,y)?"YES":"NO");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ARTS习惯(8)
    ARTS习惯(7)
    ARTS习惯(6)
    ARTS习惯(5)
    ARTS习惯(4)
    ARTS习惯(3)
    线程状态
    java线程同步
    数据库视图
    数据库事务
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7501574.html
Copyright © 2020-2023  润新知