hdu 5893 List wants to travel 树链剖分 +线段树
来源:互联网 发布:arcgis能安装在mac吗 编辑:程序博客网 时间:2024/06/06 15:04
http://acm.hdu.edu.cn/showproblem.php?pid=5893
题意:
题意:一棵无根树,两种操作:改变路径上的颜色,和询问路径上有多少段颜色。
裸的树链剖分+线段树维护颜色段,
唯一难点就是合并的时候 如果两个区间段颜色一样,ans--,链同理。
http://blog.csdn.net/viphong/article/details/52167628 一个月前写的原题。。。。。。。真tm蠢,
原题是 点权,那么只需要查询时,判断当前链的顶端与链子的顶端的父亲是否同色即可。(或者判断链子的末端与last链的top是否同色)
而现在是边权,则我们分开判断lca(u,v)对应的两条链即可
即 int lastu=-1,col,lastv=-1;
对于 查询一条 f1到u的链,
求u的颜色 col=query_single(1,1,pos,p[u]);
if (col==lastu) tmp--;
---------------------------------------------------------------------------
最后u和v在一条链时,分别判断 u和lastu,v和lastv是否相等 (if u==v只判断一次即可)
珍爱生命,记得update时判断u==v不要update
//BZOJ4034#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;typedef long long ll;const int MAXN = 100000+50;struct Edge{ int to,next,w; Edge() {} Edge(int a,int b,int c) { to=a,next=b,w=c; }} edge[MAXN*2],edge2[MAXN];int head[MAXN],tot;int top[MAXN];//top[v]表示v所在的重链的顶端节点int fa[MAXN]; //父亲节点int deep[MAXN];//深度int num[MAXN];//num[v]表示以v为根的子树的节点数int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置int fp[MAXN];//和p数组相反int son[MAXN];//重儿子int pos;int out[MAXN];//dfs序int n,m;void init(){ tot = 0; memset(head,-1,sizeof(head)); pos = 0; memset(son,-1,sizeof(son));}void addedge(int u,int v,int w){ edge[tot].to = v; edge[tot].next = head[u]; edge[tot].w=w; head[u] = tot++;}void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son{ deep[u] = d; fa[u] = pre; num[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != pre) { dfs1(v,u,d+1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } }}void getpos(int u,int sp) //第二遍dfs求出top和p{ top[u] = sp; p[u] = ++pos; fp[p[u]] = u; if(son[u]!=-1) getpos(son[u],sp); for(int i = head[u] ; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u]) getpos(v,v); } out[u]=pos;}struct TREE{ int sum[4*MAXN],add[4*MAXN], numl[MAXN<<2], numr[MAXN<<2]; void init() { memset(sum,0,sizeof sum); memset(add,0,sizeof add); memset(numl,0,sizeof numl); memset(numr,0,sizeof numr); } void build(int l,int r,int i) // 线段树的建立; { add[i]=-1; //add[rt]=aa[++ok]; sum[i]=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); } void pushUp(int i) { sum[i]=sum[i<<1]+sum[i<<1|1]-(numr[i<<1]==numl[i<<1|1]); numl[i]=numl[i<<1]; numr[i]=numr[i<<1|1]; } void pushDown(int i, int l, int r)//把i节点的延迟标记传递到左右儿子节点 { if(add[i] != -1) { add[i<<1]=add[i<<1|1]=add[i]; numl[i<<1]=numl[i<<1|1]=add[i]; numr[i<<1]=numr[i<<1|1]=add[i]; sum[i<<1]=sum[i<<1|1]=1; add[i]=-1; } } void update(int i, int l, int r, int ql,int qr, int c) //更新区间为qlqr,当前区间为l,r,代表当前区间和的节点为i,更新值为val, { if(l > qr ||ql > r)//更新区间不在当前区间内 return ; if(l >=ql && r <=qr )//要更新的区间把当前区间完全包括,则把当前整个区间+val,然后返回上一层 { sum[i]=1; add[i]=numl[i]=numr[i]=c; return ; } pushDown(i, l, r);//如果上面没reutrn 表示要往左右儿子区间查询,所以把延迟标记放下去 int mid = (l + r) >> 1; update(i << 1, l, mid, ql,qr, c); update(i << 1 | 1, mid + 1, r, ql,qr, c); pushUp(i); } int query(int i, int l, int r, int ql, int qr) //查询区间为qlqr,当前区间为l,r,代表当前区间和的节点为i { if(l > qr || ql > r) return 0; if(l >= ql && r <= qr) return sum[i]; pushDown(i, l, r);//同update int m=(l+r)/2; int ret=0; if(ql<=m) ret+=query(i<<1,l,m,ql,qr); if(m<qr) ret+=query(i<<1|1,m+1,r,ql,qr); if(ql<=m&&m<qr) ret-=(numr[i<<1]==numl[i<<1|1]); return ret; } int query_single(int i, int l, int r, int x) //查询区间为qlqr,当前区间为l,r,代表当前区间和的节点为i { if(l ==r ) return add[i]; pushDown(i, l, r);//同update int m=(l+r)/2; if(x<=m) return query_single(i<<1,l,m,x); return query_single(i<<1|1,m+1,r,x); } int findsum(int u,int v)//查询u->v链的sum { int f1=top[u],f2=top[v]; int tmp=0; int lastu=-1,col,lastv=-1; while(f1!=f2) { if (deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); swap(lastu,lastv); } tmp+=query(1,1,pos,p[f1],p[u]); col=query_single(1,1,pos,p[u]); if (col==lastu) tmp--; lastu=query_single(1,1,pos,p[f1]); u=fa[f1],f1=top[u]; } if (u!=v) { if (deep[u]>deep[v] ) swap(u,v),swap(lastu,lastv); tmp+=query(1,1,pos,p[son[u]],p[v]); col=query_single(1,1,pos,p[v]); if (col==lastv) tmp--; col=query_single(1,1,pos,p[son[u]]); if (col==lastu) tmp--; } else if (lastu==lastv) tmp--; return tmp; ; //若val(u)是u到fu的边权,则用son[u] } int update_edge(int u,int v,int c)//查询u->v链的sum { int f1=top[u],f2=top[v]; ll tmp=0; while(f1!=f2) { if (deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } update(1,1,pos,p[f1],p[u],c); u=fa[f1],f1=top[u]; } if (deep[u]>deep[v] ) swap(u,v); if (u!=v) update(1,1,pos,p[son[u]],p[v],c); }};TREE tp;ll a[MAXN];int main(){ int tt; // freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { init(); int u,v,w; int num=0; tp.init(); for (int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); edge2[++num]=Edge(u,v,w); } dfs1(1,0,0); getpos(1,1); tp.build(1,pos,1); for (int i=1; i<=num; i++) { int u=edge2[i].next; int v=edge2[i].to; int w=edge2[i].w; if (fa[u]==v) tp.update(1,1,pos,p[u],p[u],w); //son->fa的边权为e[i][2] else tp.update(1,1,pos,p[v],p[v],w); //son->fa的边权为e[i][2] } char op[20]; for (int i=1; i<=m; i++) { int a,b,c; scanf("%s%d%d", op, &a, &b); if (op[0]=='Q') printf("%d\n",tp.findsum(a,b)); else { scanf("%d",&c); tp.update_edge(a,b,c); } } } return 0;}
0 0
- hdu 5893 List wants to travel 树链剖分 +线段树
- HDU 5893 List wants to travel 【线段树+树链剖分】
- Hdu-5893 List wants to travel(树链剖分)
- [树链剖分] HDU 5893 List wants to travel
- HDU 5893 List wants to travel 树链剖分
- HDU 5893 List wants to travel (树链剖分,线段树区间合并)
- hdu5893 List wants to travel(树链剖分+线段树)
- hdu5893 List wants to travel(树链剖分+线段树)
- 2016 ACM/ICPC Reginal Shengyang hdu 5893 List wants to travel(树链剖分 线段树区间更新真蛋疼)★
- HDU 5893 List wants to travel
- hdu 5893 List wants to travel
- HDU 5893 List wants to travel
- [HDU 5893] List wants to travel (树链剖分+区间合并)
- HDU 5893 List wants to travel 树链剖分 边权剖分
- HDU 5893 List wants to travel(树链剖分+区间合并)
- hdu 5893 List wants to travel 树链剖分求区间段数
- HDU5893 List wants to travel (树链剖分 + 线段树) 2016 ACM/ICPC Asia Regional Shenyang Online
- List wants to travel
- java基础知识
- Unity Editor(二)C#特性与Editor
- ANSI C,C90,C99
- mac下安装docker
- java基础知识(续)
- hdu 5893 List wants to travel 树链剖分 +线段树
- Android RecyclerView 使用完全解析 体验艺术般的控件
- java基础知识-继承
- 项目总结(FDL)(一)ListView单选和多项
- 《Wide & Deep Learning for Recommender Systems 》笔记
- javascript高级程序设计第三版 第4章 基本类型和引用类型的值 学习笔记
- java基础知识-内部类
- Unity Editor(三)Resources目录限制不能出现中文
- C++Primer(第八章课后习题程序题源代码)