2016 ACM/ICPC Asia Regional Shenyang Online HDU 5893 List wants to travel
2016-09-19 18:42
477 查看
List wants to travel
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 331 Accepted Submission(s): 66
[align=left]Problem Description[/align]
A boy named List who is perfect in English. Now he wants to travel and he is making a plan. But the cost of living in same citie always changes. Now he wants to know how many different kinds of continuous same cost he has to pay for
living between two cities. Can you help him? (He is so lazy to do this by himself.)
[align=left]Input[/align]
There are multiple cases. The first line contains two positive numbers N and M(N (N<=40000) where N is the amount of cities and M (M<=50000)) is the amount of operations.Then N-1 lines where each line have 3 integers a b and c, representing
that there is a bidirectionoal road between city a and city b, and the cost is c.(a != b and c <= 100000). Then there are M lines of operation. For example, "Change a b c" means changing all the costs of the road which are passed by him when he travels from
city a to city b to c. "Query a b" means he wants you to tell him how many different kinds of continuous same cost he has to pay traveling from city a to city b.(if a == b, the cost is 0).
[align=left]Output[/align]
He insure you that there is exactly one route between every two different cities.
[align=left]Sample Input[/align]
9 3 1 2 2 2 3 1 1 7 2 1 4 2 3 5 2 3 6 1 5 8 2 5 9 3 Query 1 8 Change 2 6 3 Query 1 6
[align=left]Sample Output[/align]
3 2
【题意】一颗无根树,两种操作:改变路径上的颜色,和询问路径上有多少段颜色。
【解题方法】算是bzoj原题了。。。bzoj 2243,不过bzoj上是点权,这里是边权,改一下就可以A了。这题之前写过,当时参考了这篇blog:http://blog.csdn.net/viphong/article/details/52167628
【具体分析】
原题是 点权,那么只需要查询时,判断当前链的顶端与链子的顶端的父亲是否同色即可。(或者判断链子的末端与last链的top是否同色),而现在是边权,则我们分开判断lca(u,v)对应的两条链即可即 。 int lastu=-1,col,lastv=-1;对于 查询一条 f1到u的链,求u的颜色 col=query_col(1,1,pos,p[u]);if
(col==lastu) tmp--;最后u和v在一条链时,分别判断 u和lastu,v和lastv是否相等 (if u==v只判断一次即可)
【AC 代码】
// //Created by just_sort 2016/9/12 17:37 //Copyright (c) 2016 just_sort.All Rights Reserved // #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 100050; struct Edge { int to,next,w; Edge(){} Edge(int a,int b,int c){to=a,next=b,w=c;} }edge[maxn*2],tmp[maxn]; int head[maxn],tot,n,m,top[maxn],fa[maxn],dep[maxn],num[maxn],tid[maxn],son[maxn],tim; void init(){ tot = tim = 0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); } void addedge(int u,int v,int w){ edge[tot]={v,head[u],w}; head[u] = tot++; } void dfs1(int u,int pre,int d) { dep[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 dfs2(int u,int tp) { top[u] = tp; tid[u] = ++tim; if(son[u]!=-1) dfs2(son[u],tp); for(int i = head[u] ; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u]) dfs2(v,v); } } struct SegmentTree { int sum[4*maxn],add[4*maxn], numl[maxn*4], numr[maxn*4]; 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 rt) { add[rt] = -1; sum[rt] = 0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void pushUp(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]-(numr[rt<<1]==numl[rt<<1|1]); numl[rt]=numl[rt<<1]; numr[rt]=numr[rt<<1|1]; } void pushDown(int rt, int l, int r) { if(add[rt] != -1) { add[rt<<1]=add[rt<<1|1]=add[rt]; numl[rt<<1]=numl[rt<<1|1]=add[rt]; numr[rt<<1]=numr[rt<<1|1]=add[rt]; sum[rt<<1]=sum[rt<<1|1]=1; add[rt]=-1; } } void update(int rt, int l, int r, int L,int R, int c) { if(l > R || L > r) return ; if(l >=L && r <=R ) { sum[rt]=1; add[rt]=numl[rt]=numr[rt]=c; return ; } pushDown(rt, l, r); int mid = (l + r) >> 1; update(rt << 1, l, mid, L,R, c); update(rt << 1 | 1, mid + 1, r, L,R, c); pushUp(rt); } int query(int rt, int l, int r, int L, int R) { if(l > R || L > r) return 0; if(l >= L && r <= R) return sum[rt]; pushDown(rt, l, r); int m=(l+r)/2; int ret=0; if(L<=m) ret+=query(rt<<1,l,m,L,R); if(m<R) ret+=query(rt<<1|1,m+1,r,L,R); if(L<=m&&m<R) ret-=(numr[rt<<1]==numl[rt<<1|1]); return ret; } int querycol(int rt, int l, int r, int x) { if(l==r) return add[rt]; pushDown(rt, l, r); int m=(l+r)/2; if(x<=m) return querycol(rt<<1,l,m,x); return querycol(rt<<1|1,m+1,r,x); } int queryans(int u,int v) { int f1=top[u],f2=top[v]; int tmp=0; int cur; int lastu=-1,lastv=-1; while(f1!=f2) { if (dep[f1]<dep[f2]){ swap(f1,f2); swap(u,v); swap(lastu,lastv); } tmp+=query(1,1,tim,tid[f1],tid[u]); cur=querycol(1,1,tim,tid[u]); if (cur==lastu) tmp--; lastu=querycol(1,1,tim,tid[f1]); u=fa[f1],f1=top[u]; } if (u!=v) { if (dep[u]>dep[v] ) swap(u,v),swap(lastu,lastv); tmp+=query(1,1,tim,tid[son[u]],tid[v]); cur=querycol(1,1,tim,tid[v]); if (cur==lastv) tmp--; cur=querycol(1,1,tim,tid[son[u]]); if (cur==lastu) tmp--; } else if (lastu==lastv) tmp--; return tmp; } void negnate(int u,int v,int c) { int f1=top[u],f2=top[v]; while(f1!=f2) { if (dep[f1]<dep[f2]) { swap(f1,f2); swap(u,v); } update(1,1,tim,tid[f1],tid[u],c); u=fa[f1],f1=top[u]; } if (dep[u]>dep[v] ) swap(u,v); if (u!=v) update(1,1,tim,tid[son[u]],tid[v],c); } }tree; int main() { int u,v,w; while(scanf("%d%d",&n,&m)!=EOF) { init(); tree.init(); for (int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); tmp[i]=Edge(u,v,w); } dfs1(1,0,0); dfs2(1,1); tree.build(1,tim,1); for (int i=1; i<n; i++) { u=tmp[i].next,v=tmp[i].to,w=tmp[i].w; if (fa[u]==v) tree.update(1,1,tim,tid[u],tid[u],w); else tree.update(1,1,tim,tid[v],tid[v],w); } char op[10]; for (int i=1; i<=m; i++) { scanf("%s%d%d",op,&u,&v); if (op[0]=='Q'){ if(u==v) printf("0\n"); else printf("%d\n",tree.queryans(u,v)); } else{ scanf("%d",&w); tree.negnate(u,v,w); } } } return 0; }
相关文章推荐
- 模板【HDU5893 2016 ACM ICPC Asia Regional Shenyang Online B】【树链剖分 权在边上 链值合并 结构体写法】List wants to travel
- HDU5893 List wants to travel (树链剖分 + 线段树) 2016 ACM/ICPC Asia Regional Shenyang Online
- hdu 5893 List wants to travel 2016ACM/ICPC沈阳赛区网络赛1002
- 2016 ACM/ICPC Reginal Shengyang hdu 5893 List wants to travel(树链剖分 线段树区间更新真蛋疼)★
- HDU 5898 odd-even number (数位DP) 2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5894 hannnnah_j’s Biologica(lucas定理求组合数+乘法逆元)——2016 ACM/ICPC Asia Regional Shenyang Online
- 2016 ACM/ICPC Asia Regional Shenyang Online 1007/HDU 5898 数位dp
- 2016 ACM/ICPC Asia Regional Shenyang Online 1003/HDU 5894 数学/组合数/逆元
- HDU 5898 odd-even number (数位DP) 2016 ACM/ICPC Asia Regional Shenyang Online
- hdu 5900 QSC and Master 区间dp(2016 ACM/ICPC Asia Regional Shenyang Online)
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5901 Count Primes (模板 + 数论知识)★
- HDU 5895 Mathematician QSC(逆元应用+矩阵快速幂+数论知识)——2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5900 QSC and Master(2016 ACM/ICPC Asia Regional Shenyang Online)
- HDU 5895&&2016 ACM/ICPC Asia Regional Shenyang Online1004 Mathematician QSC [矩阵加速+欧拉降幂]【数论】
- HDU 5898&&2016 ACM/ICPC Asia Regional Shenyang Online/ odd-even number [数位DP]【动态规划】
- HDU 5898 odd-even number(2016 ACM/ICPC Asia Regional Shenyang Online)
- HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)——2016 ACM/ICPC Asia Regional Shenyang Online
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5895 Mathematician QSC
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5895 Mathematician QSC(矩阵快速幂+高次幂取模)★ ★
- hdu 5892 List wants to travel 2016ACM/ICPC沈阳赛区网络赛1001