HDU 5893 List wants to travel(树链剖分)
【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=5893
【题目大意】
给出一棵树,每条边上都有一个边权,现在有两个操作,操作一要求将x到y路径上所有边更改为c权值,操作二要求查询x到y的路径上有几段连续的权值相同的。
【题解】
首先由于是边权,所以把所有边的存下来,做一遍剖分,将权值保存在每条边深度较深的点上,作为点权,用区间合并线段树维护区间内的线段段数,沿链修改的时候注意剖分出的区间的起点是不更新的,因为边权变成点权之后链修改的LCA是不修改的。查询的时候由于边权转点权之后点权位置的特殊性,我们每次在查询a到b之间的答案的时候,首先求出两者的LCA,同时求出LCA到a和b之间的第一个点,求分别求出a和b与其第二root之间的答案,再判断一下交接处的情况,就能计算出答案。
【代码】
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1000000;
int tot,x,d[N],num[N],ed=0,u,w,n,m,i,v[N],vis[N],f[N],g[N],nxt[N],size[N],son[N],st[N],en[N],dfn,top[N],t;char ch;
void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
size[x]=1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
f[v[i]]=x,d[v[i]]=d[x]+1;
dfs(v[i]),size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
if(x==-1)return;
st[x]=++dfn;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
en[x]=dfn;
}
int T[N<<2],mark[N<<2],cl[N<<2],cr[N<<2],L,R;
void up(int x){
T[x]=T[x<<1]+T[x<<1|1]-(cr[x<<1]==cl[x<<1|1]);
cl[x]=cl[x<<1];
cr[x]=cr[x<<1|1];
}
void pushdown(int x,int l,int r){
if(l==r)return;
if(mark[x]!=-1){
mark[x<<1]=mark[x<<1|1]=mark[x];
cl[x<<1]=cl[x<<1|1]=mark[x];
cr[x<<1]=cr[x<<1|1]=mark[x];
T[x<<1]=T[x<<1|1]=1;
mark[x]=-1;
}
}
void update(int x,int l,int r,int c){
pushdown(x,l,r);
if(L<=l&&r<=R){T[x]=1;mark[x]=cl[x]=cr[x]=c;return;}
int mid=(l+r)/2;
if(L<=mid)update(x<<1,l,mid,c);
if(mid<R)update(x<<1|1,mid+1,r,c);
up(x);
}
void update(int l,int r,int c){
if(l>r)return;
L=l;R=r; update(1,1,n,c);
}
int query(int x,int l,int r){
pushdown(x,l,r);
if(L<=l&&r<=R)return T[x];
int mid=(l+r)/2,ret=0;
if(L<=mid)ret+=query(x<<1,l,mid);
if(mid<R)ret+=query(x<<1|1,mid+1,r);
if(L<=mid&&mid<R)ret-=(cr[x<<1]==cl[x<<1|1]);
return ret;
}
int query(int l,int r){L=l;R=r;return query(1,1,n);}
int color(int x,int l,int r,int f){
if(l==r)return cl[x];
pushdown(x,l,r);
int mid=(l+r)/2;
if(f<=mid)return color(x<<1,l,mid,f);
return color(x<<1|1,mid+1,r,f);
}
int query(int l){return color(1,1,n,l);}
void chain(int x,int y,int c){
for(;top[x]!=top[y];x=f[top[x]]){
if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
update(st[top[x]],st[x],c);
}if(d[x]<d[y]){int z=x;x=y;y=z;}
update(st[y]+1,st[x],c);
}
int find(int x,int y){
int ret=0;
for(;top[x]!=top[y];x=f[top[x]]){
if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
ret+=query(st[top[x]],st[x]);
ret-=(query(st[top[x]])==query(st[f[top[x]]]));
}if(d[x]<d[y]){int z=x;x=y;y=z;}
ret+=query(st[y],st[x]);
return ret;
}
int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
return d[x]<d[y]?x:y;
}
int lca2(int x,int y){
int t;
while(top[x]!=top[y])t=top[y],y=f[top[y]];
return x==y?t:son[x];
}
void init(){
for(int i=0;i<n*4;i++)T[i]=1,mark[i]=-1;
memset(g,dfn=ed=0,sizeof(g));
memset(v,0,sizeof(v));
memset(nxt,0,sizeof(nxt));
memset(son,-1,sizeof(son));
}
int cas;
int e[N][3];
int main(){
while(~scanf("%d%d",&n,&m)){
init();
for(int i=0;i<n-1;i++){
scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
add(e[i][0],e[i][1]);
add(e[i][1],e[i][0]);
}dfs(1);dfs2(1,1);
for(int i=0;i<n-1;i++){
if(d[e[i][0]]>d[e[i][1]])swap(e[i][0],e[i][1]);
update(st[e[i][1]],st[e[i][1]],e[i][2]);
}char op[10]; int a,b,c;
//for(int i=1;i<=n;i++)printf("%d\n",st[i]);
while(m--){
scanf("%s",op);
scanf("%d%d",&a,&b);
if(op[0]=='Q'){
c=lca(a,b);
int fa=lca2(c,a);
int fb=lca2(c,b);
//printf("%d %d %d\n",c,fa,fb);
//printf("%d %d\n",query(st[fa]),query(st[fb]));
if(a==b)puts("0");
else if(c==a)printf("%d\n",find(b,fb));
else if(c==b)printf("%d\n",find(a,fa));
else printf("%d\n",find(a,fa)+find(b,fb)-(query(st[fa])==query(st[fb])));
}else{
scanf("%d",&c);
chain(a,b,c);
}
}
}return 0;
}
HDU 5893 List wants to travel(树链剖分)的更多相关文章
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- HDU 4897 Little Devil I(树链剖分)(2014 Multi-University Training Contest 4)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 Problem Description There is an old country and ...
- HDU 5274 Dylans loves tree(树链剖分)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- HDU - 3966 Aragorn's Story(树链剖分入门+线段树)
HDU - 3966 Aragorn's Story Time Limit: 3000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...
- hdu 3966 Aragorn's Story(树链剖分+区间修改+单点查询)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上 ...
- hdu5893 List wants to travel(树链剖分+线段树)
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submissi ...
- (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。
Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...
随机推荐
- php7 不向后的兼容的变更
php7 不向后的兼容的变更 在php7中,很多致命错误以及可恢复的致命错误,都被转换为异常来处理了. 这些异常继承自Error类,此类实现了Throwable接口(所有异常都实现了这个基础接口) 这 ...
- 用OxyPlot在WPF中演示正演磁异常的变化规律
为了在展示实验成果时动态演示理论球体磁异常随其埋深.磁化倾角的变化规律,我用WPF写了一个小程序来作演示. MatLab计算磁异常数据 首先是计算理论球体磁异常数据,在Matlab中可以很方便地计算. ...
- ASP.NET Identity 系列笔记目录
编写目的 混迹博客园已经有一段时间了,一直都是在学习各路大神的文章,自己却没有做出什么贡献,所以觉得应该写一点点内容和大家一起分享.但是本人实在才疏学浅,有心无力啊!正好最近在学习 Microsoft ...
- 供应类型与计划分类一致性检查(INV)
应用 Oracle Inventory 层 Level Function 函数名 Funcgtion Name CUXINVIMM 表单名 Form Name CUXINVIMM 说明 Descrip ...
- 使用gSoap做一个简单的CS系统
首先介绍一下gSoap,这是一个非常厉害的网络库,封装程度非常高而且跨平台. 支持SSL链接,数据格式为XML. 介绍地址: http://sourceforge.net/projects/gsoap ...
- Windows Azure Web Role 的 IIS 重置
如果您是一名 Web开发人员,您很可能使用过"简单快捷"的iisreset命令重置运行不正常的 IIS主机.这种方法通常在经典的 Windows Server VM上非常有效 ...
- MCI 函数与命令
Microsoft 提供的 MMSYSTEM.H 文件中定义了调用 MCI 功能的数据类型和函数原型.在使用 MCI 功能的任何源模块中都应包含该文件. 1. MCI 函数 所有的 MCI 函数名都以 ...
- HDU 4308 BFS Saving Princess claire_
原题直通车:HDU 4308 Saving Princess claire_ 分析: 两次BFS分别找出‘Y’.‘C’到达最近的‘P’的最小消耗.再算出‘Y’到‘C’的最小消耗,比较出最小值 代码: ...
- 为什么需要Page Object?
为什么需要Page Object? Page Object(PO)是界面自动化验收测试中的一个常见模式,要和@槽神刘叫兽探讨一下PO的必要性,顾写这篇小文表达一下我的观点. PO的主要价值体现在对界面 ...
- 利用Socket实现的两个程序的通信
写的也很简单,自己觉得挺有意思了 程序如图 主要代码 public class Message { Form1 mainfrom = null; public Message() { } public ...