2018 有志气博士来种草

来源:互联网 发布:mac高频电磁阀 编辑:程序博客网 时间:2024/04/29 19:27

Task
N节点的树,m个操作分2种:
① (x,y)路径上的各边的值+1
② 询问边(x,y)的值。

Solution
方法一:树链剖分
树链剖分使用于树上的区间更新或者区间询问,把链重新编号,加入线段树中。

方法二:刷漆法
问题属于区间更新,单点求值。
如果在序列上,可以用刷漆法+前缀和得到每个点的权值。
在树上可以转化成两段区间,即(x,lca),(y,lca)同样的左端点+1,右端点+1的位置-1
结论:x到父亲的边权值=x子树的权值和

但是暴力dfs x的子树会超时,如果把x的子树变成连续的一段,就可以用线段树进行区间求值。而dfs序可以将一棵子树变成连续的一段。

int L[M],R[M],fa[S][M],head[M],dep[M];int n,m,ecnt,tot;struct edge{    int t,nxt;}e[M<<1];struct Segment_Tree{    int t[M<<2];//存当前点的值     inline void update(int l,int r,int x,int a,int p){        if(l==r){            t[p]+=a;            return;        }           int mid=l+r>>1;        if(x<=mid)update(l,mid,x,a,lsn(p));        else update(mid+1,r,x,a,rsn(p));        t[p]=t[lsn(p)]+t[rsn(p)];    }    inline int query(int L,int R,int l,int r,int p){        if(l==L&&r==R)return t[p];        int mid=L+R>>1;        if(r<=mid)return query(L,mid,l,r,lsn(p));        else if(l>mid)return query(mid+1,R,l,r,rsn(p));        else return query(L,mid,l,mid,lsn(p))+query(mid+1,R,mid+1,r,rsn(p));    }}T;struct P100{    inline void addedge(int f,int t){        e[++ecnt]=(edge){t,head[f]};        head[f]=ecnt;    }    inline void input(){        int a,b;        rd(n);rd(m);        rep(i,1,n-1){            rd(a);rd(b);            addedge(a,b);            addedge(b,a);        }    }    inline void dfs(int f,int x,int d){        fa[0][x]=f;        dep[x]=d;        L[x]=++tot;        tral(i,x){            if(e[i].t!=f)dfs(x,e[i].t,d+1);        }        R[x]=tot;    }    inline int LCA(int x,int y){        if(dep[x]<dep[y])swap(x,y);        int d=dep[x]-dep[y];        rep(i,0,S-1){            if(d&(1<<i))x=fa[i][x];        }        if(x==y)return x;        per(i,S-1,0){            if(fa[i][x]!=fa[i][y]){                x=fa[i][x];                y=fa[i][y];            }        }        return fa[0][x];    }    inline void solve(){        int a,b;        char str[10];        rep(i,1,m){            scanf("%s",str);            rd(a);rd(b);            if(str[0]=='P'){//add                T.update(1,n,L[a],1,1);                T.update(1,n,L[b],1,1);                T.update(1,n,L[LCA(a,b)],-2,1);            }            else{                if(dep[a]<dep[b])swap(a,b);                sc(T.query(1,n,L[a],R[a],1));//子树的和             }        }    }    inline void init(){        rep(i,1,S-1)            rep(j,1,n)fa[i][j]=fa[i-1][fa[i-1][j]];    }    inline void MAIN(){        input();            dfs(0,1,0);        init();        solve();    }}P100;
0 0