HDU 5893 List wants to travel

来源:互联网 发布:网络信号传输增强器 编辑:程序博客网 时间:2024/05/22 08:20

HDU 5893 List wants to travel

树链剖分,边权

题目

给出2种操作

  1. 修改u到v的路径上的边的颜色为c
  2. 查询u到v的路径上有多少段颜色

思路

根bzoj2243差不多,就是把点权改成边权。把边权下放到深度大的点的点权。维护起来没有想的复杂。

先往重链头跳,跳完判断一下l是否跟r一样。一样说明汇合,不需要继续查了。否则查的时候要避开端点,可以查重儿子,看代码吧。

代码

树链剖分多组样例,记得把hson和depth数组清掉。

#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cstdlib>#include<iostream>#include<cmath>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define M(a,b) memset(a,b,sizeof(a))using namespace std;const int MAXN=50007;typedef long long LL;struct Edge{    int to, ne, val;}G[MAXN*2];int head[MAXN];int Val[MAXN], Hson[MAXN], SonAmount[MAXN], Father[MAXN], Depth[MAXN];int Dfsnum[MAXN], TreeValue[MAXN], TopOfHeavyChain[MAXN];int dfscount, edgenum;void AddEdge(int from, int to, int v){    G[edgenum].to=to, G[edgenum].val=v, G[edgenum].ne=head[from];head[from]=edgenum++;    G[edgenum].to=from, G[edgenum].val=v, G[edgenum].ne=head[to];head[to]=edgenum++;}void init(){    M(head, -1);M(G, 0);    M(Hson, 0);M(Depth, 0);    dfscount=0;edgenum=1;Val[1]=0;Father[1]=1;Depth[1]=1;}void dfs1(int n){    SonAmount[n]=1;    for(int i=head[n];~i;i=G[i].ne)    {        int to=G[i].to;        if(Depth[to]) continue;        Depth[to]=Depth[n]+1;        Val[to]=G[i].val;//边权转化为点权        Father[to]=n;        dfs1(to);        SonAmount[n]+=SonAmount[to];        if(SonAmount[to]>SonAmount[Hson[n]]) Hson[n]=to;    }    return;}void dfs2(int n, int prev){    Dfsnum[n]=++dfscount;    TreeValue[dfscount]=Val[n];    TopOfHeavyChain[n]=prev;    if(!Hson[n]) return;    dfs2(Hson[n], prev);    for(int i=head[n];~i;i=G[i].ne)    {        int to=G[i].to;        if(to==Hson[n]||to==Father[n]) continue;        dfs2(to, to);    }}struct Stree{    int lcol, rcol;    int lazy;int num;    Stree() { lcol=rcol=lazy=-1;num=0; }    void init() { lcol=rcol=lazy=-1;num=0; }}stree[MAXN<<2];inline void pushup(int rt){    stree[rt].num=stree[rt<<1].num+stree[rt<<1|1].num;    if(stree[rt<<1].rcol==stree[rt<<1|1].lcol) stree[rt].num--;    stree[rt].lcol=stree[rt<<1].lcol, stree[rt].rcol=stree[rt<<1|1].rcol;}inline void pushdown(int rt){    if(stree[rt].lazy!=-1)    {        int c=stree[rt].lazy;stree[rt].lazy=-1;        stree[rt<<1].lazy=stree[rt<<1|1].lazy=c;        stree[rt<<1].num=stree[rt<<1|1].num=1;        stree[rt<<1].lcol=stree[rt<<1|1].lcol=c;        stree[rt<<1].rcol=stree[rt<<1|1].rcol=c;    }}void build(int l, int r, int rt){    stree[rt].init();    if(l==r) { stree[rt].lcol=stree[rt].rcol=TreeValue[l];stree[rt].num=1;return; }    int mid=(l+r)>>1;    build(lson), build(rson);    pushup(rt);}void update(int L, int R, int c, int l, int r, int rt){    if(L<=l&&r<=R)    {        stree[rt].lcol=stree[rt].rcol=c;        stree[rt].lazy=c;        stree[rt].num=1;        return;    }    pushdown(rt);    int mid=(l+r)>>1;    if(L<=mid) update(L, R, c, lson);    if(mid<R) update(L, R, c, rson);    pushup(rt);}Stree query(int L, int R, int l, int r, int rt){    if(L<=l&&r<=R) return stree[rt];    pushdown(rt);    int mid=(l+r)>>1;    if(R<=mid) return query(L, R, lson);    else if(mid<L) return query(L, R, rson);    else    {        Stree lres=query(L, R, lson);        Stree rres=query(L, R, rson);        Stree res;        res.num=lres.num+rres.num-(lres.rcol==rres.lcol);        res.lcol=lres.lcol, res.rcol=rres.rcol;        return res;    }}void solveup(int n){    int l, r, c;scanf("%d%d%d", &l, &r, &c);    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];    while(fl!=fr)    {        if(Depth[fl]>Depth[fr])        {            update(Dfsnum[fl], Dfsnum[l], c, 1, n, 1);            l=Father[fl];fl=TopOfHeavyChain[l];        }        else        {            update(Dfsnum[fr], Dfsnum[r], c, 1, n, 1);            r=Father[fr];fr=TopOfHeavyChain[r];        }    }    if(l==r) return;    if(Depth[l]>Depth[r])        update(Dfsnum[Hson[r]], Dfsnum[l], c, 1, n, 1);    else update(Dfsnum[Hson[l]], Dfsnum[r], c, 1, n, 1);}void solvequ(int n){    int l, r;scanf("%d%d", &l, &r);    //if(l==r) { printf("-1\n");return; }    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];    int lcol=-1, rcol=-1, res=0;    while(fl!=fr)    {        if(Depth[fl]>Depth[fr])        {            Stree lc=query(Dfsnum[fl], Dfsnum[l], 1, n, 1);            res+=lc.num;            if(lcol==lc.rcol) res--;            lcol=lc.lcol;            l=Father[fl];            fl=TopOfHeavyChain[l];        }        else        {            Stree rc=query(Dfsnum[fr], Dfsnum[r], 1, n, 1);            res+=rc.num;            if(rcol==rc.rcol) res--;            rcol=rc.lcol;            r=Father[fr];            fr=TopOfHeavyChain[r];        }    }    if(l!=r)    {        if(Depth[l]>Depth[r])        {            Stree lc=query(Dfsnum[Hson[r]], Dfsnum[l], 1, n, 1);            res+=lc.num;            if(lcol==lc.rcol) res--;            if(rcol==lc.lcol) res--;        }        else        {            Stree rc=query(Dfsnum[Hson[l]], Dfsnum[r], 1, n, 1);            res+=rc.num;            if(lcol==rc.lcol) res--;            if(rcol==rc.rcol) res--;        }    }    else    {        res-=(lcol==rcol);    }    printf("%d\n", res);}int main(){    //freopen("in.txt", "r", stdin);    //freopen("ou1.txt", "w", stdout);    int n, m;    while(scanf("%d%d", &n, &m)==2)    {        init();        for(int i=1;i<n;i++)        {            int u, v, c;scanf("%d%d%d", &u, &v, &c);            AddEdge(u, v, c);        }        dfs1(1), dfs2(1, 1);build(1, n, 1);        while(m--)        {            char s[10];            scanf("%s", s);            if(s[0]=='Q') solvequ(n);            else solveup(n);        }    }    //system("pause");    return 0;}