HDU5893 List wants to travel (树链剖分 + 线段树) 2016 ACM/ICPC Asia Regional Shenyang Online

来源:互联网 发布:淘宝网pu羽绒服 编辑:程序博客网 时间:2024/05/21 20:29

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5893


题目大意:一棵树,两种操作:改变路径上的颜色,和询问路径上有多少段相邻颜色不同。


解题思路:树链剖分,跟BZOJ2243题目几乎一样,只不过这里是边权,把边权转化成点权,边权赋予给深度大的节点。然后用线段树维护。



/* ***********************************************┆  ┏┓   ┏┓ ┆┆┏┛┻━━━┛┻┓ ┆┆┃       ┃ ┆┆┃   ━   ┃ ┆┆┃ ┳┛ ┗┳ ┃ ┆┆┃       ┃ ┆┆┃   ┻   ┃ ┆┆┗━┓ 马 ┏━┛ ┆┆  ┃ 勒 ┃  ┆      ┆  ┃ 戈 ┗━━━┓ ┆┆  ┃ 壁     ┣┓┆┆  ┃ 的草泥马  ┏┛┆┆  ┗┓┓┏━┳┓┏┛ ┆┆   ┃┫┫ ┃┫┫ ┆┆   ┗┻┛ ┗┻┛ ┆************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <bitset>using namespace std;#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)#define per(i,a,b) for (int i=(b),_ed=(a);i>=_ed;i--)#define pb push_back#define mp make_pairconst int inf_int = 2e9;const long long inf_ll = 2e18;#define inf_add 0x3f3f3f3f#define mod 1000000007#define LL long long#define ULL unsigned long long#define MS0(X) memset((X), 0, sizeof((X)))#define SelfType intSelfType Gcd(SelfType p,SelfType q){return q==0?p:Gcd(q,p%q);}SelfType Pow(SelfType p,SelfType q){SelfType ans=1;while(q){if(q&1)ans=ans*p;p=p*p;q>>=1;}return ans;}#define Sd(X) int (X); scanf("%d", &X)#define Sdd(X, Y) int X, Y; scanf("%d%d", &X, &Y)#define Sddd(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)#define reunique(v) v.resize(std::unique(v.begin(), v.end()) - v.begin())#define all(a) a.begin(), a.end#define   mem(x,v)      memset(x,v,sizeof(x))typedef pair<int, int> pii;typedef pair<long long, long long> pll;typedef vector<int> vi;typedef vector<long long> vll;inline int read(){int ra,fh;char rx;rx=getchar(),ra=0,fh=1;while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();if(rx=='-')fh=-1,rx=getchar();while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;}//#pragma comment(linker, "/STACK:102400000,102400000")const int N = 40005;int n,m;int a[N*4];struct Edge{    int to,from,nx,w;}edge[N*2];int head[N],cnt;void addedge(int u,int v,int w){    edge[cnt] = Edge{v,u,head[u],w};    head[u] = cnt++;}/*树链剖分*/int top[N],fa[N],son[N],dep[N];int siz[N],tot,tid[N],fp[N];void dfs1(int u,int father,int d){    dep[u] = d;    fa[u] = father;    siz[u] = 1;    for(int i=head[u];i!=-1;i=edge[i].nx)    {        int v = edge[i].to;        if(v==father)continue;        dfs1(v,u,d+1);        siz[u] += siz[v];        if(son[u]==-1 || siz[v]>siz[son[u]])            son[u] = v;    }}void dfs2(int u,int tp){    top[u] = tp;    tid[u] = ++tot;    fp[tot] = u;    if(son[u]==-1)return;    dfs2(son[u],tp);    for(int i=head[u];i!=-1;i=edge[i].nx)    {        int v = edge[i].to;        if(v==son[u] || v==fa[u])continue;        dfs2(v,v);    }}/*线段树*/struct node{    int col;    int lc,rc,sum;}seg[N*4];void pushup(int rt){    seg[rt].sum = seg[rt<<1].sum + seg[rt<<1|1].sum;    seg[rt].lc = seg[rt<<1].lc;    seg[rt].rc = seg[rt<<1|1].rc;    if(seg[rt<<1].rc == seg[rt<<1|1].lc)        seg[rt].sum--;}void pushdown(int rt){    if(seg[rt].col)    {        seg[rt<<1].col = seg[rt<<1|1].col = 1;        seg[rt].col = 0;        seg[rt<<1].sum = seg[rt<<1|1].sum = 1;        seg[rt<<1].lc = seg[rt<<1].rc = seg[rt].lc;        seg[rt<<1|1].lc = seg[rt<<1|1].rc = seg[rt].rc;    }}void build(int rt,int l,int r){    seg[rt].col = 0;    if(l==r)    {        seg[rt].sum = 1;        seg[rt].lc = seg[rt].rc = a[fp[r]];        //printf("%d\n",a[fp[l]]);        return;    }    int mid = (l+r) >> 1;    build(rt<<1,l,mid);    build(rt<<1|1,mid+1,r);    pushup(rt);}void update(int rt,int l,int r,int L,int R,int c){    if(L<=l && r<=R)    {        seg[rt].col = 1;        seg[rt].lc = seg[rt].rc = c;        seg[rt].sum = 1;        return;    }    pushdown(rt);    int mid = (l+r) >> 1;    if(L<=mid) update(rt<<1,l,mid,L,R,c);    if(R>mid) update(rt<<1|1,mid+1,r,L,R,c);    pushup(rt);}node query(int rt,int l,int r,int L,int R){    if(L<=l && r<=R)    {        return seg[rt];    }    pushdown(rt);    int mid = (l+r) >> 1;    if(R<=mid) return query(rt<<1,l,mid,L,R);    else if(L>mid) return query(rt<<1|1,mid+1,r,L,R);    else    {        node p1 = query(rt<<1,l,mid,L,R);        node p2 = query(rt<<1|1,mid+1,r,L,R);        node res;        res.sum = p1.sum + p2.sum;        res.lc = p1.lc;        res.rc = p2.rc;        if(p1.rc==p2.lc) res.sum--;        return res;    }}void change(int x,int y,int z){    while(top[x]!=top[y])    {        if(dep[top[x]]<dep[top[y]])swap(x,y);        update(1,1,n,tid[top[x]],tid[x],z);        x = fa[top[x]];    }    if(x==y) return;    if(dep[x]<dep[y]) swap(x,y);    update(1,1,n,tid[son[y]],tid[x],z);}int solve(int x,int y){    int ans = 0;    int cx=-1,cy=-1;    while(top[x]!=top[y])    {        if(dep[top[x]]<dep[top[y]])        {            swap(x,y);swap(cx,cy);        }        node tmp = query(1,1,n,tid[top[x]],tid[x]);        ans += tmp.sum;        if(tmp.rc==cx) ans--;        cx = tmp.lc;        x = fa[top[x]];    }    if(x==y)    {        if(cx==cy)ans--;        return ans;    }    if(dep[x]<dep[y])    {        swap(x,y);swap(cx,cy);    }    node tmp = query(1,1,n,tid[son[y]],tid[x]);    ans += tmp.sum;    if(tmp.lc == cy) ans--;    if(tmp.rc == cx) ans--;    return ans;}char s[10];void init(){    memset(head,-1,sizeof head);    memset(son,-1,sizeof son);    cnt = 0;    tot = 0;}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);//ios::sync_with_stdio(0);//cin.tie(0);while(~scanf("%d%d",&n,&m))    {        init();        for(int i=1;i<n;i++)        {            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w);            addedge(v,u,w);        }        dfs1(1,-1,0);        dfs2(1,1);        for(int i=0;i<cnt;i+=2)        {            int x = edge[i].to;            int y = edge[i].from;            if(dep[x]<dep[y])swap(x,y);            a[x] = edge[i].w;        }        build(1,1,n);        while(m--)        {            scanf("%s",s);            int a,b,c;            if(s[0]=='Q')            {                scanf("%d%d",&a,&b);                if(a==b)printf("0\n");                else                {                    printf("%d\n",solve(a,b));                }            }            else            {                scanf("%d%d%d",&a,&b,&c);                change(a,b,c);            }        }    }return 0;}


0 0
原创粉丝点击