当前位置 博文首页 > 文章内容

    CF1386C Joker 双指针+动态树

    作者: 栏目:未分类 时间:2020-07-30 16:00:53

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    双指针+LCT.     

    在二分图那道题中,有一种用 LCT 维护奇环的方法.   

    该题的做法和那道题相似.      

    对于 $i$,维护 $left[i]$ 表示当删除 $i$ 时最靠左的端点使得删掉 $[left[i]+1,i]$ 后仍然存在奇环.      

    那么最后判断答案的时候就看 $(l,r)$ 中的 $l$ 是否大于 $left[r]$ 即可.       

    由于删掉边一定不会使答案更优,所以 $i$ 增加时 $left[i]$ 不会减小,故 $[left[i],i]$ 满足双指针性质(即不存在包含的情况)   

    将边分为两类:

    1. 由于 $i$ 变大被删掉的. 

    2. 由于双指针中左端点的移动被加入的.    

    显然对于 $1$ 类边希望出现时间越晚越好,对于 $2$ 类边没有要求.   

    根据上述结论,我们在预处理边的时候贪心加入即可(即加不进去就不加)     

    然后双指针移动的时候去替换结束时间最小的边,类似最大生成树.          

    #include <cstdio>  
    #include <cstring>
    #include <algorithm>
    #define N 400008  
    #define ll long long  
    #define ls s[x].ch[0] 
    #define rs s[x].ch[1] 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;    
    const int inf=100000000;   
    int det[N]; 
    int left[N],sta[N<<1],vis[N<<1],n,m,Q;    
    struct Edge {   
        int u,v,t;         
        Edge(int u=0,int v=0,int t=0):u(u),v(v),t(t){}  
    }a[N],arr[N]; 
    struct data {  
        int ch[2],rev,f,v,id,si,t;       
    }s[N<<2];  
    inline int get(int x) { return s[s[x].f].ch[1]==x; } 
    inline int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; }   
    void pushup(int x) {      
        s[x].id=x;     
        s[x].si=(x<=n)+s[ls].si+s[rs].si;      
        if(ls&&s[s[ls].id].t<s[s[x].id].t) { 
            s[x].id=s[ls].id; 
        }  
        if(rs&&s[s[rs].id].t<s[s[x].id].t) { 
            s[x].id=s[rs].id;   
        }  
    }
    void mark(int x) { 
        s[x].rev^=1,swap(ls,rs);  
    }  
    void pushdown(int x) { 
        if(s[x].rev) {  
            if(ls) mark(ls); 
            if(rs) mark(rs); 
            s[x].rev=0; 
        } 
    }    
    void rotate(int x) {  
        int old=s[x].f,fold=s[old].f,which=get(x); 
        if(!isr(old)) { 
            s[fold].ch[s[fold].ch[1]==old]=x;  
        }  
        s[old].ch[which]=s[x].ch[which^1];  
        if(s[old].ch[which]) s[s[old].ch[which]].f=old;  
        s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;  
        pushup(old),pushup(x);  
    } 
    void splay(int x) { 
        int u=x,v=0,fa; 
        for(sta[++v]=u;!isr(u);u=s[u].f) { 
            sta[++v]=s[u].f;  
        }    
        for(;v;--v) pushdown(sta[v]);  
        for(u=s[u].f;(fa=s[x].f)!=u;rotate(x))  
            if(s[fa].f!=u) { 
                rotate(get(fa)==get(x)?fa:x);  
            }
    }
    void access(int x) { 
        for(int y=0;x;y=x,x=s[x].f) {    
            splay(x),rs=y,pushup(x);  
        }
    }   
    void makert(int x) {
        access(x),splay(x),mark(x);  
    }      
    void split(int x,int y) {  
        makert(x),access(y),splay(y);  
    }   
    int find(int x) {  
        access(x),splay(x);          
        while(ls) pushdown(x),x=ls; 
        splay(x);  
        return x;  
    }
    void ADD(int x,int y) { 
        makert(x),s[x].f=y; 
    }
    void DEC(int x,int y) {   
        makert(x),access(y),splay(y);  
        s[y].ch[0]=s[x].f=0;  
        pushup(y);  
    }
    void exi(int lst) { 
        if(lst==0) { 
            for(int i=1;i<=Q;++i) {     
                int x,y;  
                scanf("%d%d",&x,&y); 
                printf("NO\n"); 
            } 
            exit(0); 
        }
    }        
    int main() { 
        // setIO("input");           
        int x,y,z; 
        scanf("%d%d%d",&n,&m,&Q);   
        for(int i=1;i<=m;++i) { 
            scanf("%d%d",&x,&y);  
            arr[i]=Edge(x,y,i);  
        }         
        int lst=0;         
        a[0].t=inf;  
        for(int i=1;i<=n;++i) { 
            s[i].t=inf;   
            s[i].id=i; 
        }
        for(int i=m;i>=1;--i) {      
            x=arr[i].u;   
            y=arr[i].v;      
            a[i]=arr[i];  
            if(find(x)==find(y)) {   
                split(x,y);        
                if(s[y].si&1) {    
                    lst=i;   
                    break;   
                }
            }
            else {    
                int now=n+i;         
                s[now].v=i;        
                s[now].t=i;     
                pushup(now); 
                vis[i]=1;    
                ADD(x,now),ADD(y,now);  
            }
        }         
        int tot=n+m;  
        exi(lst);     
        int p=1,cnt=0; 
        for(int i=lst;i<=m;++i) {           
            int flag=0;      
            for(cnt+=det[i];!cnt&&p<=i;++p) {              
                a[m+p]=arr[p];  
                x=arr[p].u,y=arr[p].v;   
                if(find(x)==find(y)) {     
                    split(x,y);     
                    int pr=s[y].id; 
                    int nx=s[pr].v;        
                    if(s[y].si&1) {        
                        ++cnt,--det[a[nx].t];            
                    }                   
                    if(a[nx].t<=m) {     
                        vis[s[y].id-n]=0; 
                    }     
                    DEC(pr,a[nx].u); 
                    DEC(pr,a[nx].v);                    
                }               
                int now=++tot;  
                a[m+p].t=m+1;         
                s[now].v=m+p;   
                s[now].t=m+1;    
                pushup(now),ADD(now,x),ADD(now,y);                 
            }          
            left[i]=p-1;                             
            if(i+1<=m&&vis[i+1]) {   
                vis[i+1]=0;    
                int now=i+1+n;  
                DEC(now,arr[i+1].u); 
                DEC(now,arr[i+1].v);         
            }
        }
        for(int i=1;i<=Q;++i) { 
            scanf("%d%d",&x,&y);   
            if(y<lst) { 
                printf("YES\n"); 
            }  
            else { 
                if(x>left[y]) printf("YES\n");   
                else printf("NO\n"); 
            } 
        }
        return 0; 
    }