CSU 1607: Do You Have The Template?(树链剖分)边权
来源:互联网 发布:union软件安卓版 编辑:程序博客网 时间:2024/04/30 04:52
1607: Do You Have The Template?
Time Limit: 7 Sec Memory Limit: 128 MBSubmit: 112 Solved: 8
[Submit][Status][Web Board]
Description
There is a tree with N vertices, each edges have a positive length.
And here comes 4 operations,
0 a b, means query the maximum length and the sum of length on the path between vertex a and vertex b.
1 a b, means change the a-th edge's length to b.
2 a b 0 c, means change all edges' length on the path between vertex a and vertex b to c.
2 a b 1 c, means add all edges' length on the path between vertex a and vertex b by c.
Input
There're several cases.
The first line contains a positive integer N (2 <= N <= 10000), meaning there're N vertices, marked 1 to N. Then N – 1 lines follow with the i-th line describing the i-th edge. Each line contains three integers a b c, meaning there is an edge between vertex a and vertex b with the length of c.
Then one integer M (M <= 10000), means there're M queries. And followed by M lines, each line will contain one operation described as above.
Output
For each 0 a b query, you should output the maximum length and the sum.
The data insure no number will be bigger than 2^31.
Sample Input
41 2 12 3 22 4 3100 1 30 1 40 3 41 2 30 1 32 4 3 0 20 1 42 4 3 1 20 1 30 1 4
Sample Output
2 33 43 53 42 34 54 5
题意:给出一棵树有n个节点,每个边有权值,现在有M个操作:
0 a b 表示输出从a点到b点的路径的边权最大值和边树总和。
1 a b 表示第a条边的权值变为b
2 a b 0 c 表示从a点到b点的路径的每条边权都变成c
2 a b 1 c 表示从a点到b点的路径的每条边权都加上c
坑点:在CSU的这道题用vector建图就WA。标程代码有漏洞,就是用root[k].toc去判断是否需要更新线段树中k的左右子节点。
解题:用树链剖分,边权变点权。用线段树去维护边权。
#include<stdio.h>#include<string.h>#include<vector>const int N=10015;using namespace std; int head[N], to[N << 1], next1[N << 1], tot;int top[N]; //top[v]=u表示点v,u在一个链中,且u是这个链深度最小的点(即顶端)int fath[N]; //记录父节点int deep[N]; //每个点在树上的深度int num[N]; //每棵子树的节点个数int son[N]; //选的重边子节点int p[N]; //树上每个点在线段树中所对应的点int pos; void addEdge(const int& u, const int& v) { to[tot] = v, next1[tot] = head[u], head[u] = tot++;} void addUndirEdge(const int& u, const int& v) { addEdge(u, v), addEdge(v, u);} void init(int n){ pos=0; tot=0; memset(son,-1,sizeof(son)); memset(head,-1,sizeof(head));}void dfs1(int u,int pre,int d){ deep[u]=d; fath[u]=pre; num[u]=1; for (int i = head[u]; i != -1; i = next1[i]) { int v = to[i]; if(v==pre)continue; 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 root){ top[u]=root; p[u]=pos++; if(son[u]==-1) return ; getpos(son[u],root); for (int i = head[u]; i != -1; i = next1[i]) { int v = to[i]; if(son[u]!=v&&v!=fath[u]) getpos(v,v); }} //线段树struct tree{ int sum,maxv,toc,addc; }root[N*4];int val[N];int MAX(int a,int b){ return a>b?a:b;}void build(int l,int r,int k){ int mid=(l+r)/2; root[k].addc=0; root[k].toc=0; if(l==r){ root[k].sum=root[k].maxv=val[l]; return ; } build(l,mid,k<<1); build(mid+1,r,k<<1|1); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv);}void upson(int k,int l,int r){ int mid=(l+r)/2; if(root[k].toc) { root[k<<1].sum=(mid-l+1)*root[k].toc; root[k<<1].maxv=root[k].toc; root[k<<1].toc=root[k].toc; root[k<<1].addc=0; root[k<<1|1].sum=(r-mid)*root[k].toc; root[k<<1|1].maxv=root[k].toc; root[k<<1|1].toc=root[k].toc; root[k<<1|1].addc=0; root[k].toc=0; } if(root[k].addc) { root[k<<1].sum+=(mid-l+1)*root[k].addc; root[k<<1].maxv+=root[k].addc; root[k<<1].addc+=root[k].addc; root[k<<1|1].sum+=(r-mid)*root[k].addc; root[k<<1|1].maxv+=root[k].addc; root[k<<1|1].addc+=root[k].addc; root[k].addc=0; }}void updata1(int l,int r,int k,const int L,const int R,int c){ if(L<=l&&r<=R) { root[k].sum=(r-l+1)*c; root[k].maxv=c; root[k].toc=c; root[k].addc=0; return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) updata1(l,mid,k<<1,L,R,c); if(mid<R) updata1(mid+1,r,k<<1|1,L,R,c); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv);}void updata2(int l,int r,int k, int L, int R,int c){ if(L<=l&&r<=R) { root[k].sum+=(r-l+1)*c; root[k].maxv+=c; root[k].addc+=c; return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) updata2(l,mid,k<<1,L,R,c); if(mid<R) updata2(mid+1,r,k<<1|1,L,R,c); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv);}int sum,maxv;void query(int l,int r,int k,int L,int R){ if(L<=l&&r<=R) { sum+=root[k].sum; maxv=MAX(maxv,root[k].maxv); return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) query(l,mid,k<<1,L,R); if(mid<R) query(mid+1,r,k<<1|1,L,R);}void swp(int &a,int &b){ int tt; tt=a; a=b; b=tt;}void Operat0(int u,int v){ int f1=top[u], f2=top[v]; sum=0; maxv=0; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } query(1,pos,1,p[f1],p[u]); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); query(1,pos,1,p[son[u]],p[v]);}void Operat1(int u,int v,int c){ int f1=top[u], f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } updata1(1,pos,1,p[f1],p[u],c); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); updata1(1,pos,1,p[son[u]],p[v],c);}void Operat2(int u,int v,int c){ int f1=top[u], f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } updata2(1,pos,1,p[f1],p[u],c); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); updata2(1,pos,1,p[son[u]],p[v],c);} struct EDG{ int u,v,c;}edg[N];int main(){ int n,q,op,a,b; while(scanf("%d",&n)!=EOF) { init(n); for(int i=1;i<n;i++) { scanf("%d%d%d",&edg[i].u,&edg[i].v,&edg[i].c); addUndirEdge(edg[i].u, edg[i].v); } dfs1(1,1,1); getpos(1,1); pos=n; for(int i=1;i<n;i++) { if(deep[edg[i].u]>deep[edg[i].v]) edg[i].v=edg[i].u; val[p[edg[i].v]]=edg[i].c; } build(1,pos,1); scanf("%d",&q); while(q--) { scanf("%d%d%d",&op,&a,&b); if(op==0) { Operat0(a,b); printf("%d %d\n",maxv,sum); } else if(op==1) updata1(1,pos,1,p[edg[a].v],p[edg[a].v],b); else { int tt,c; scanf("%d%d",&tt,&c); if(tt==0) Operat1(a,b,c); else Operat2(a,b,c); } } }} /************************************************************** Problem: 1607 User: aking2015 Language: C++ Result: Accepted Time:912 ms Memory:2180 kb****************************************************************/
- CSU 1607: Do You Have The Template?(树链剖分)边权
- CSU 1607: Do You Have The Template?
- CSU 1607: Do You Have The Template?(基于边权的树链剖分的完善模板)
- ubuntu the folder contents could not be display ,you do not have the permission(解决办法)
- What do you really have?
- [Code Sample]Alert "Do you want to save the changes you have made?"
- You do not appear to have the sources for the 3.5.0-23-generic kernel installed
- runInstaller-- you do not have sufficient permissions to access the inventory
- Unable to access the IIS metabase.You do not have sufficient privilege
- git push updates were rejected because the remote contain works that you do not have
- Unable to access the IIS metabase.You do not have sufficient privilege
- OpenAirInterface USRP安装时You do not have write permissions at the install location问题解决方案
- Do you have a little time
- Do I Have To Cry For You
- [每日习语] Do you have any hobbies?
- “you do not have permissions to run”
- It appears as though you do not have permission to view information for any of the hosts you request
- 51 You have not configured Oracle Managed Files (OMF) in your database. You do not want to scan the
- 牡丹江的水题们
- ZOJ 3593 One Person Game (扩展欧几里得)
- linux下安装nginx
- Leetcode 74 Search a 2D Matrix 有序二维数组二叉查找
- Spring3学习笔记之(spring core之DI配置使用1)
- CSU 1607: Do You Have The Template?(树链剖分)边权
- 整理牛人看文献的方法
- 研究生、科研人员须知的文献管理软件及一个学术会议网站
- Git 命令速查手册
- cocos2dx 3.2在Eclipse上打包出现error: call of overloaded 'abs(float)' is ambiguous
- Cookie使用时需要注意个数及大小限制
- 1--黑马程序员--7k面试题之银行业务系统
- Android源代码 之 下载源代码
- 深入探讨ListView使用