zoukankan      html  css  js  c++  java
  • Max Mex

    Max Mex

    无法直接处理

    可以二分答案!

    [0,mid]是否在同一个链上?

    可以不修改地做了

    修改?

    能不能信息合并?可以!

    记录包含[l,r]的最短链的两端

    可以[0,k][k+1,mid]合并:枚举四个端点中的两个,使得另外两个一定在这两个的路径上

    (判断z点在x,y路径上:(lca(x,z)==z||lca(y,z)=z)&&(lca(lca(x,y),z)=lca(x,y))画图即可理解

    能合并,所以线段树可以维护。

    线段树维护

    线段树上二分。

    LCA用ST表存

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=2e5+5;
    int n,q;
    struct node{
        int nxt,to;
    }e[2*N];
    int hd[N],cnt;
    void add(int x,int y){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int dep[N];
    int a[2*N],tot;
    int dfn[N];
    int f[2*N][20];
    int lg[2*N];
    int id[N],fid[N];
    void dfs(int x,int d){
        dep[x]=d;
        a[++tot]=x;
        dfn[x]=tot;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            dfs(y,d+1);
            a[++tot]=x;
        }
    }
    int big(int x,int y){
        return dep[x]<dep[y]?x:y;
    }
    int lca(int x,int y){
        if(dfn[x]>dfn[y]) swap(x,y);
        int len=lg[dfn[y]-dfn[x]+1];
        return big(f[dfn[x]][len],f[dfn[y]-(1<<len)+1][len]);
    }
    int on(int p1,int p2,int p3){
        int y=lca(p1,p2);
    //    cout<<" p1 "<<p1<<" p2 "<<p2<<" p3 "<<p3<<" y "<<y<<endl;
        return ((lca(p1,p3)==p3||lca(p2,p3)==p3)&&(lca(y,p3)==y));
    }
    struct tr{
        int p[2];
        int can;
        void init(){
            can=p[0]=p[1]=0;
        }
        void op(){
            cout<<" can "<<can<<" p[0] "<<p[0]<<" p[1] "<<p[1]<<endl;
        }
    }t[4*N];
    #define ls (x<<1)
    #define rs (x<<1|1)
    #define mid ((l+r)>>1)
    void pushup(int x){
        t[x].init();
        if(t[x<<1].can&&t[x<<1|1].can){
            t[x].can|=on(t[ls].p[0],t[ls].p[1],t[rs].p[0])&&on(t[ls].p[0],t[ls].p[1],t[rs].p[1]);
            if(t[x].can==1) {t[x].p[0]=t[ls].p[0],t[x].p[1]=t[ls].p[1];return;}
            t[x].can|=on(t[rs].p[0],t[rs].p[1],t[ls].p[0])&&on(t[rs].p[0],t[rs].p[1],t[ls].p[1]);
            if(t[x].can==1) {t[x].p[0]=t[rs].p[0],t[x].p[1]=t[rs].p[1];return;}
            if(!t[x].can){
                for(reg i=0;i<=1;++i){
                    for(reg j=0;j<=1;++j){
                        t[x].can|=on(t[ls].p[i],t[rs].p[j],t[ls].p[i^1])&&on(t[ls].p[i],t[rs].p[j],t[rs].p[j^1]);
                        if(t[x].can==1) {t[x].p[0]=t[ls].p[i],t[x].p[1]=t[rs].p[j];return;}
                    }
                }
            }
        }
    }
    tr merge(tr A,tr B){
        tr C;C.can=C.p[0]=C.p[1]=0;
    //    cout<<" A ";A.op();
    //    cout<<" B ";B.op();
        if(A.can&&B.can){
            C.can|=on(A.p[0],A.p[1],B.p[0])&&on(A.p[0],A.p[1],B.p[1]);
            if(C.can==1) {C.p[0]=A.p[0],C.p[1]=A.p[1];return C;}
            C.can|=on(B.p[0],B.p[1],A.p[0])&&on(B.p[0],B.p[1],A.p[1]);
            if(C.can==1) {C.p[0]=B.p[0],C.p[1]=B.p[1];return C;}
            if(!C.can){
                for(reg i=0;i<=1;++i){
                    for(reg j=0;j<=1;++j){
                        C.can|=on(A.p[i],B.p[j],A.p[i^1])&&on(A.p[i],B.p[j],B.p[j^1]);
                        if(C.can==1) {C.p[0]=A.p[i],C.p[1]=B.p[j];return C;}
                    }
                }
            }
        }
        return C;
    }
    void build(int x,int l,int r){
        if(l==r){
            t[x].p[0]=t[x].p[1]=fid[l];
            t[x].can=1;return;
        }
        t[x].can=0;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    void upda(int x,int l,int r,int p,int c){//pos to c
        if(l==r){
            t[x].p[0]=c;t[x].p[1]=c;
            t[x].can=1;return;
        }
        if(p<=mid) upda(ls,l,mid,p,c);
        else upda(rs,mid+1,r,p,c);
        pushup(x);
    }
    tr tmp;
    int query(int x,int l,int r){
    //    cout<<" query "<<x<<" "<<l<<" "<<r<<" : ";t[x].op();
        
        tr C;
        if(l==r){
            if(tmp.can==-1){
                C=t[x];
            }else{
                C=merge(tmp,t[x]);
            }
            return C.can==1?l:l-1;
        }
    //    cout<<" ls ";t[ls].op();
        if(tmp.can==-1){
            C=t[ls];
        }else{
            C=merge(tmp,t[ls]);
        }
    //    C.op();
        if(C.can){
            tmp=C;
            return query(rs,mid+1,r);
        }else{
            return query(ls,l,mid);
        }
    }
    int main(){
        rd(n);
        for(reg i=1;i<=n;++i){
            rd(id[i]);fid[id[i]]=i;
        }
        int y;
        for(reg i=2;i<=n;++i){
            rd(y);add(y,i);
        }
        dfs(1,1);
        for(reg i=1;i<=2*n-1;++i){
            lg[i]=(i>>(lg[i-1]+1))?lg[i-1]+1:lg[i-1];
            f[i][0]=a[i];
        }
    //    cout<<" tot "<<tot<<endl;
    //    prt(a,1,tot);
    //    prt(lg,1,2*n-1);
        for(reg j=1;j<=19;++j){
            for(reg i=1;i+(1<<j)-1<=tot;++i){
                f[i][j]=big(f[i][j-1],f[i+(1<<(j-1))][j-1]);
            }
        }
        build(1,0,n-1);
        
        rd(q);
        int op,x;
        while(q--){
            rd(op);
            if(op==1){
                rd(x);rd(y);
                upda(1,0,n-1,id[x],y);
                upda(1,0,n-1,id[y],x);
                swap(id[x],id[y]);
            }else{
                tmp.init();
                tmp.can=-1;
                printf("%d
    ",query(1,0,n-1)+1);
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/4/11 16:56:19
    */

    正难则反考虑二分检验。

    [IOI2018] seats 排座位有点像,维护前缀信息的连通性

    修改?能否两两区间合并?树上链的信息合并的套路。

  • 相关阅读:
    童年记忆
    展现、通讯、IO
    通电自动开机
    英雄每多屠狗辈,自古侠女出风尘(看黄金大劫案有感)
    反射整理学习<一>(转)
    在ASP.NET中跟踪和恢复大文件下载
    高内聚、低耦合
    你需要权限才能执行此操作
    WP7应用开发笔记(5) 通信设计
    一个简单的软件工程流程
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10691660.html
Copyright © 2011-2022 走看看