树链剖分+segtree+treap HYSBZ 1146 网络管理Network

来源:互联网 发布:网络教育能报四级英语 编辑:程序博客网 时间:2024/06/05 19:48

题目很好理解,因为是汉语的。。。

就是求树上的一条路径的第K大数,可修改,多组询问,当然了,对于每组询问,o(n)的时间复杂度不能接受,只能是log级别的

所以就是树链剖分,加segtree套平衡树,代码挺长的

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#define mid (L+R>>1)const int inf=~0u>>1;const int M = 80010;class Treap{public:    struct node{        node *ch[2];        int v,p,sz;        node(int _v,node *n):            v(_v){ch[0]=ch[1]=n;p=rand();sz=1;}        void update(){sz=ch[0]->sz+ch[1]->sz+1;}    };    node *root,*null;    Treap(){        null=new node(0,0);null->sz=0;null->p=inf;        null->ch[0]=null->ch[1]=null;        root=null;    }    void rotate(node *&t,bool d){        node *_t=t->ch[d];        t->ch[d]=_t->ch[!d];        _t->ch[!d]=t;        _t->update();        t->update();        t=_t;    }    void __insert(node *&t,int val){        if(t==null){            t=new node(val,null);            return;        }        bool d=val > t->v;        __insert(t->ch[d],val);        if(t->ch[d]->p < t->p)rotate(t,d);        t->update();    }    void __del(node *&t,int val){        if(t==null)return;        if(val == t->v){            bool d = t->ch[1]->p < t->ch[0]->p;            if(t->ch[d]==null){                delete t;                t=null;                return;            }            rotate(t,d);            __del(t->ch[!d],val);        }else{            bool d=val > t->v;            __del(t->ch[d],val);        }        t->update();    }    int __rank(node *t,int val){        if(t==null)return 0;        if(val > t->v)return __rank(t->ch[1],val);        return t->ch[1]->sz+1+__rank(t->ch[0],val);    }    void insert(int val){        __insert(root,val);    }    void del(int val){        __del(root,val);    }    int rank(int val){        return __rank(root,val);    }};class segtree{public:    Treap *tree[M<<2];    int val[M];    void build(int L,int R,int P){        tree[P] = new Treap;        for(int i=L;i<=R;i++){            tree[P]->insert(val[i]);        }        if(L==R)return ;        build(L,mid,P<<1);        build(mid+1,R,P<<1|1);    }    int query(int L,int R,int P,int l,int r,int val){        if(L==l&&R==r){            return tree[P]->rank(val);        }        int ret=0;        if(l<=mid){            ret+=query(L,mid,P<<1,l,min(mid,r),val);        }        if(r>mid){            ret+=query(mid+1,R,P<<1|1,max(l,mid+1),r,val);        }        return ret;    }    void update(int L,int R,int P,int p,int a,int b){        tree[P]->del(a);        tree[P]->insert(b);        if(L==R)return ;        if(p<=mid){            update(L,mid,P<<1,p,a,b);        }else{            update(mid+1,R,P<<1|1,p,a,b);        }    }};int head[M],cnt;struct Edge{    int u,v,next;    void set(int _u,int _v){        u=_u,v=_v;        next=head[u];        head[u]=cnt++;    }}edge[M<<1];segtree *tree;int son[M],pre[M],dep[M],siz[M],top[M],pos[M],tot;int val[M],n,m; void init(){    cnt=tot=0;    memset(head,-1,sizeof(head));}void dfs_1(int u,int f,int d){    pre[u]=f,dep[u]=d;    siz[u]=1,son[u]=0;    for(int i=head[u];~i;i=edge[i].next){        int v=edge[i].v;        if(v!=f){            dfs_1(v,u,d+1);            siz[u]+=siz[v];            if(siz[son[u]]<siz[v])son[u]=v;        }    }}void dfs_2(int u,int tp){    top[u]=tp,pos[u]=++tot;    if(son[u])dfs_2(son[u],tp);    for(int i=head[u];~i;i=edge[i].next){        int v=edge[i].v;        if(v!=son[u]&&v!=pre[u])dfs_2(v,v);    }}int rank(int u,int v,int vall){    int f1=top[u],f2=top[v],ret=0;    while(f1!=f2){        if(dep[f1]<dep[f2])swap(u,v),swap(f1,f2);        ret+=tree->query(1,n,1,pos[f1],pos[u],vall);        u=pre[f1],f1=top[u];    }    if(dep[u]<dep[v])swap(u,v);    return ret+tree->query(1,n,1,pos[v],pos[u],vall);}int main(){    while(~scanf("%d%d",&n,&m)){        init();        for(int i=1;i<=n;i++){            scanf("%d",&val[i]);        }        for(int i=1,u,v;i<n;i++){            scanf("%d%d",&u,&v);            edge[cnt].set(u,v);            edge[cnt].set(v,u);        }        tree = new segtree;        dfs_1(1,0,1);        dfs_2(1,1);        for(int i=1;i<=n;i++){            tree->val[pos[i]]=val[i];        }        tree->build(1,n,1);        while(m--){            int k,a,b;            scanf("%d%d%d",&k,&a,&b);            if(k){                int L=0,R=(int)1e8,f=0;                while(L<=R&&!f){                    int aa=rank(a,b,mid+1);                    int bb=rank(a,b,mid);                    if(k>aa&&k<=bb){                        f=1;                        printf("%d\n",mid);                    }                    k>aa?R=mid-1:L=mid+1;                   }                if(!f)puts("invalid request!");            }else{                tree->update(1,n,1,pos[a],val[a],b);                val[a]=b;            }        }    }    return 0;   }


0 0
原创粉丝点击