• [某模拟赛]鸡腿の乒乓



    要求支持操作(次数10^5):
    1、插入一个区间[x,y],保证比之前所有区间都长
    2、询问第a个区间能否走到第b个区间
    [a,b]能走到[c,d]=>c<a<d或c<b<d

    考虑[a,b]能走到的所有区间是 从端点开始类似dfs走到的所有区间的并,显然这个并也是一个区间。
    我们考虑维护这个东西。用并查集维护区间的联通块(块内区间能互相到达),记下最左和最右
    我们考虑所有严格包含点a的区间,他们都是能与[a,b]合并的,找这个可以用线段树维护
    SGT上每个节点[x,y]开一个vet记下所有当前完整覆盖这个[x,y]的所有区间,查询时暴力扫
    每次我们[a,b]先合并完 然后[a,b]扩展到了[a',b'],我们将其插到SGT中
    对于SGT上那些旧的区间 我们不用立即删掉 在我们查询的时候判断一下当前这个区间是否被合并了即可

    询问时我们考虑哪些区间能走到[a,b]
    我们考虑[a,b]所在联通块的左右[a',b'],如果一个区间[c,d]且a'<c<d<b',那么[c,d]能走到[a',b'],因为他们在同一个联通块中。(注意如果a'=c<d=b'是不行的。)

    复杂度?每次插入覆盖logn个节点,由于题目中条件“比之前所有区间都长”所以合并时的复杂度是可以保证的。查询是O(1)的。总的好像是O(nlogn)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<vector>
    #include<map>
    #include<queue>
    #include<string>
    #include<bitset>
    #include<iomanip>
    #include<iostream>
    #include<cmath>
    using namespace std;
    
    #define rep(i,x,y) for(i=x;i<=y;i++)
    #define _rep(i,x,y) for(i=x;i>=y;i--)
    #define CL(S,x) memset(S,x,sizeof(S))
    #define CP(S1,S2) memcpy(S1,S2,sizeof(S2))
    #define ALL(x,S) for(x=S.begin();x!=S.end();x++)
    #define sqr(x) ((x)*(x))
    #define mp make_pair
    #define fi first
    #define se second
    #define upmin(x,y) x=min(x,y)
    #define upmax(x,y) x=max(x,y)
    #define pb push_back
    #define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endl
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int,int> pii;
    
    int read(int&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;return x;}
    inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
    
    const int N=100010;
    int m,g,i,j,k,l,p,id;
    int DQ[N],V[N<<1];
    int numV(int x){return lower_bound(V+1,V+1+V[0],x)-V;}
    
    struct ask
    {
        int id,t,l,r;
        void input(int i){read(t);if(t==1){V[++V[0]]=read(l);V[++V[0]]=read(r);id=++g;DQ[id]=i;}else read(l),read(r);}
    }Q[N];
    
    struct UnionSet
    {
        int f[N],l[N],r[N];
        void init(){int i;rep(i,1,g)f[i]=i;}
        int get(int x){return f[x]==x?x:f[x]=get(f[x]);}
        void Union(int x,int y){f[x]=y;upmin(l[y],l[x]);upmax(r[y],r[x]);}
        void merge(int x,int y){x=get(x);y=get(y);Union(x,y);}
    }U;
    
    struct SGT
    {
        vector<int> T[N<<2];
        void ins(int i,int x,int y,int l,int r)
        {
            if(y<l||x>r)return;
            if(x>=l&&y<=r){T[i].pb(id);return;}
            ins(i*2,x,(x+y)/2,l,r);
            ins(i*2+1,(x+y)/2+1,y,l,r);
        }
        #define del(A,i) swap(A[i],A.back()),A.pop_back(),--i
        void ext(int i,int x,int y,int d)
        {
            for(int t=0;t<T[i].size();t++)
            {
                int p=U.get(T[i][t]);
                if(p!=T[i][t])del(T[i],t);
                else if(U.l[p]<d&&d<U.r[p])U.merge(p,id),del(T[i],t);
            }
            if(x!=y)if(d<=(x+y)/2)ext(i*2,x,(x+y)/2,d);else ext(i*2+1,(x+y)/2+1,y,d);
        }
        void add(int now)
        {
            id=now;int a=U.l[now],b=U.r[now];
            ext(1,1,V[0],a);
            ext(1,1,V[0],b);
            a=U.l[now];b=U.r[now];
            ins(1,1,V[0],a,b);
        }
    }T;
    
    
    void work()
    {
        int p,l,r;
        rep(p,1,m)
        {
            if(Q[p].t==1)
            {
                U.l[Q[p].id]=Q[p].l=numV(Q[p].l);
                U.r[Q[p].id]=Q[p].r=numV(Q[p].r);
                T.add(Q[p].id);
            }
            else
            {
                l=DQ[Q[p].l];r=U.get(Q[p].r);
                if(U.l[r]<=Q[l].l&&Q[l].r<=U.r[r])printf("YES
    ");else printf("NO
    ");
            }
        }
    }
    
    
    int main()
    {
        //freopen("1.in","r",stdin);freopen("1.out","w",stdout);
        
        int i,j;
        read(m);rep(i,1,m)Q[i].input(i);U.init();
        sort(V+1,V+1+V[0]);j=1;rep(i,2,V[0])if(V[i]!=V[i-1])V[++j]=V[i];V[0]=j;
        
        work();
            
        scanf("
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    机器学习简介
    正则表达式
    JDK5特性
    Eclipse简介和使用
    泛型(Generic)
    集合
    sqlserver 存储过程 分页搜索查询
    asp.net mvc 接入最新支付宝支付+退款 alipay-sdk-NET-20170615110549
    asp.net mvc 接入阿里大于 短信验证码发送
    sqlserver 存储过程 递归查询分组+hierarchyid重建会员关系
  • 原文地址:https://www.cnblogs.com/oldmanren/p/3623723.html
Copyright © 2020-2023  润新知