HDU 5893 List wants to travel
树链剖分,边权
题目
给出2种操作
- 修改u到v的路径上的边的颜色为c
- 查询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;
}