• bzoj3514(主席树+lct)


    把边的编号看成边权,维护每个状态对应的最大生成树,得到一个数组a[i],表示第i条边在这个过程中替换的是那条边,询问时看一下a[l,r]内啊有多少个小于l的算一下答案就好;代码参考:http://blog.csdn.net/thy_asdf/article/details/50518526

    //lct不好处理边权,把一条边转成夹在两个点之间的点; 
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=400010,maxt=10000010,inf=1e9;
    struct edg{
        int u,v;
    }e[maxn];
    struct node{
        int l,r,v;
    }tr[maxt];
    int n,m,k,tot,root[maxn],a[maxn],type,lastans;
    void insert(int t,int l,int r,int &x){
        ++tot;tr[tot]=tr[x];x=tot;
        ++tr[tot].v;
        if(l==r)return;
        int mid=l+r>>1;
        if(t<=mid)insert(t,l,mid,tr[x].l);
        else insert(t,mid+1,r,tr[x].r);
    }
    int qs(int x,int y,int l,int r,int L,int R){
        if(r<L||l>R||l>r)return 0;
        if(l>=L&&r<=R)return tr[y].v-tr[x].v;
        int mid=l+r>>1;
        return qs(tr[x].l,tr[y].l,l,mid,L,R)+qs(tr[x].r,tr[y].r,mid+1,r,L,R); 
    }
    struct node2{
        int ls,rs,fa,is_root;
    }tre[maxn];
    int siz[maxn],mins[maxn],val[maxn],cnt,rev[maxn];
    void update(int x){
        mins[x]=x;
        if(val[mins[tre[x].ls]]<val[mins[x]])mins[x]=mins[tre[x].ls];
        if(val[mins[tre[x].rs]]<val[mins[x]])mins[x]=mins[tre[x].rs];
    }
    void flip(int x){swap(tre[x].ls,tre[x].rs);rev[x]^=1;}
    void pushdown(int x){if(rev[x])flip(tre[x].ls),flip(tre[x].rs),rev[x]^=1;}
    void relax(int x){if(tre[x].fa)relax(tre[x].fa);pushdown(x);}
    void rx(int x){
        int y=tre[x].fa,z=tre[y].fa;
        tre[y].ls=tre[x].rs;
        if(tre[x].rs)tre[tre[x].rs].fa=y;
        tre[x].rs=y;tre[y].fa=x;
        tre[x].fa=z;
        if(z&&!tre[y].is_root){
            if(tre[z].ls==y)tre[z].ls=x;else tre[z].rs=x;
        }
        if(tre[y].is_root)tre[x].is_root=1,tre[y].is_root=0;
        update(y);update(x);
    }
    void lx(int x){
        int y=tre[x].fa,z=tre[y].fa;
        tre[y].rs=tre[x].ls;
        if(tre[x].ls)tre[tre[x].ls].fa=y;
        tre[x].ls=y;tre[y].fa=x;
        tre[x].fa=z;
        if(z&&!tre[y].is_root){
            if(tre[z].ls==y)tre[z].ls=x;else tre[z].rs=x;
        }
        if(tre[y].is_root)tre[x].is_root=1,tre[y].is_root=0;
        update(y);update(x);
    }
    void splay(int x){
        relax(x);
        while(!tre[x].is_root){
            //cout<<"orz"<<endl;
            int y=tre[x].fa,z=tre[y].fa;
            if(tre[y].is_root){if(tre[y].ls==x)rx(x);else lx(x);}
            else{
                if(tre[z].ls==y&&tre[y].ls==x){rx(y);rx(x);}
                else if(tre[z].ls==y&&tre[y].rs==x){lx(x);rx(x);}
                else if(tre[z].rs==y&&tre[y].ls==x){rx(x);lx(x);}
                else {lx(y);lx(x);}
            }
        }
    }
    void ace(int x){
        int y=0;
        do{
            splay(x);
            if(tre[x].rs)tre[tre[x].rs].is_root=1;
            tre[tre[x].rs=y].is_root=0;
            update(x);
            x=tre[y=x].fa;
        }while(x);
    }
    void makeroot(int x){ace(x);splay(x);flip(x);}
    void link(int x,int y){makeroot(x);tre[x].fa=y;}
    void cut(int x,int y){makeroot(x);ace(y);splay(y);tre[y].ls=tre[x].fa=0;tre[x].is_root=1;}//一开始最后这句话丢了; 
    int findrt(int x){ace(x);splay(x);for(;tre[x].ls;x=tre[x].ls);return x;}
    int query(int x,int y){makeroot(x);ace(y);splay(y);return mins[y];}
    void pre(){
        for(int i=1;i<=n+m;++i)tre[i].is_root=1;
        cnt=n;
        for(int i=1;i<=m;++i){
            int u=e[i].u,v=e[i].v;
            if(u==v){a[i]=i;continue;}
            if(findrt(u)==findrt(v)){
                int cp=query(u,v),x=val[cp];
                a[i]=x;cut(e[x].u,cp);cut(e[x].v,cp);
            }
            ++cnt;mins[cnt]=cnt;val[cnt]=i;link(u,cnt);link(v,cnt);
        }
        for(int i=1;i<=m;++i){
            root[i]=root[i-1];insert(a[i],0,m,root[i]);
        }
    }
    int main(){
        cin>>n>>m>>k>>type;
        val[0]=inf;
        for(int i=1;i<=n;++i)mins[i]=i,val[i]=inf;
        for(int i=1;i<=m;++i)scanf("%d%d",&e[i].u,&e[i].v);
        pre();
        int l,r;
        for(int i=1;i<=k;++i){
            scanf("%d%d",&l,&r);
            if(type)l^=lastans,r^=lastans;
            printf("%d
    ",lastans=(n-qs(root[l-1],root[r],0,m,0,l-1)));
        } 
        return 0;
    } 
  • 相关阅读:
    Uniprot Accession的格式以及正则表达式
    python正则表达式统计字符串的个数
    apache开启图片缓存压缩
    mysql之备份表和备份数据库
    linux下lampp的启动和停止脚本
    linux下tomcat的启动,停止,重启脚本
    文件上传PHP
    Assembly测试
    List之Sort使用
    Ienumerable和Ienumerator的使用
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8508750.html
Copyright © 2020-2023  润新知