HDU 5044 Tree(LCA ,2014上海网络赛1003)
来源:互联网 发布:淘宝代付可以信用卡吗 编辑:程序博客网 时间:2024/04/27 22:20
题目:Tree
题意:又是一棵树,两种操作:
ADD1 U V K:将U到V结点路上的结点的权值都增加K;
ADD2 U V K:将U到V结点路上的边的权值都增加K;
最后输出所有点和所有边的权值。
我的做法是找到U, V的最近公共祖先X。
add[i][0]表示第i个点的权值。
des[i]表示第i个点在计算完之后,应该减少的权值。
add[i][1]表示第i个点跟其父结点之间的边的权值。
如果是操作1:
add[U][0] += K;add[V][0] += K;add[X][0] -= K;des[X] += K;
如果是操作2:
add[U][1] += K;add[V][1] += K;add[X][1] -= K*2;
这里作下解释:
因为我最后是从叶子结点出发往他们的父亲传递。
对于第一种操作,肯定U到X的路径的结点增加K,V到X的路径也增加K。
所以我们可以通过将add[U][0]和add[V][0]的信息不断传递上去,直到X为止。
由于U和V都会传递一个K给X,所以add[X][0]减掉一个K。
处理完X了,K不能再传给其父节点,所以再用des[X]减掉一次。
对于第二种操作,同理,也是不断将信息向上传递。但由于这里是边,不会算两次,所以直接在X的位置减掉两倍K即可。
传递的时候,可以搞个队列不断把叶子结点(deg为0)的添加进去,处理就行了。
最后注意下N=1的时候,虽然没有边,但是输出边权还是要留个空行给它。比赛因此吃了个久违的PE。。。
#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>using namespace std;const int N = 100001;const int LOG = 20;#pragma comment(linker, "/STACK:102400000,102400000")#define pb push_backstruct Edge{ int to, id; Edge(){} Edge(int to, int id):to(to),id(id){}};;vector<Edge> V[N];typedef long long LL;LL add[N][2], des[N], node[N], edge[N];int n;int parent[LOG][N];int depth[N], top[N];int deg[N];void dfs(int x, int fa){parent[0][x] = fa;deg[x]=0;for(int i=0; i<V[x].size(); i++){ Edge &e = V[x][i];int j = e.to;if(j!=fa){ deg[x]++; top[j] = e.id;depth[j] = depth[x]+1;dfs(j, x);}}}void init(){depth[1] = 0;dfs(1, -1);for(int k=0; k+1<LOG; k++){for(int v=1; v<=n; v++){if(parent[k][v]<0)parent[k+1][v]=-1;elseparent[k+1][v] = parent[k][parent[k][v]];}}}int lca(int u, int v){if(depth[u]>depth[v])swap(u, v);for(int k=0; k<LOG; k++){if((depth[v]-depth[u]) >> k&1){v = parent[k][v];}}if(u==v)return u;for(int k=LOG-1; k>=0; k--){if(parent[k][u]!=parent[k][v]){u = parent[k][u];v = parent[k][v];}}return parent[0][u];}void solve(){ queue<int> Q; for(int i=1; i<=n; i++){ if(!deg[i]) Q.push(i); } while(!Q.empty()){ int x=Q.front(); Q.pop(); node[x] = add[x][0]; add[x][0] -= des[x]; int j = parent[0][x]; add[j][0] += add[x][0]; add[j][1] += add[x][1]; edge[top[x]] = add[x][1]; if(!(--deg[j])) Q.push(j); }}inline void in(int &x){ x = 0; bool mk = 0; char c=getchar(); while(c<48 || c>57){ if(c=='-') mk=1; c=getchar(); } while(c>=48 &&c<=57){ x = x*10+c-48; c = getchar(); } if(mk) x = -x;}int main(){ //freopen("C.txt", "r", stdin); //freopen("C2.txt", "w", stdout); int T, q; in(T); for(int t=1; t<=T; t++){ in(n); in(q); for(int i=1; i<=n; i++){ V[i].clear(); add[i][0] = add[i][1] = 0; des[i] = 0; } int a, b, c; char op[10]; for(int i=1; i<n; i++){ in(a); in(b); V[a].pb(Edge(b, i)); V[b].pb(Edge(a, i)); } init(); while(q--){ scanf("%s", op); in(a); in(b); in(c); int x = lca(a, b); if(op[3]=='1'){ add[a][0] += c; add[b][0] += c; add[x][0] -= c; des[x] += c; } else{ add[a][1] += c; add[b][1] += c; add[x][1] -= c*2; } } solve(); printf("Case #%d:\n", t); for(int i=1; i<=n; i++){ printf("%I64d%c", node[i], i==n?'\n':' '); } for(int i=1; i<n; i++){ printf("%I64d%c", edge[i], i==n-1?'\n':' '); } if(n==1) puts(""); } return 0;}
0 0
- HDU 5044 Tree(LCA ,2014上海网络赛1003)
- hdu5044 Tree 上海网络赛1003 LCA+输入输出外挂
- HDU 5044 Tree (2014年上海赛区网络赛C题)
- HDU5044 2014上海网络赛1003 tree
- HDU 5044 Tree(LCA)
- HDU 5045 Contest (2014上海网络赛)
- hdu 5050 Divided Land---2014acm上海赛区网络赛
- hdu 5045 Contest--2014acm上海赛区网络赛
- hdu 5053 the Sum of Cube(上海网络赛)
- HDU 5052 Yaoge’s maximum profit(树链剖分+线段树,2014上海网络赛1011)
- HDU 5045 Contest(概率dp,状态压缩,2014上海网络赛1004)
- HDU 5046 Airport (2014年上海赛区网络赛E题)
- HDU Tree LCA 2014 ACM/ICPC Asia Regional Shanghai Online
- 2014上海网络赛Contest
- HDU 4912 - Paths on the tree (LCA 贪心)
- HDU 4912 Paths on the tree (LCA+贪心)
- HDU 4912 Paths on the tree(LCA+贪心)
- HDU 5293 Tree chain problem(树形DP+树链剖分+LCA)
- 虾卣稼彝当糙寻温汹稚计诠值妥昂
- 猿撬派碧谑狭厥麓仍怪狭群蔽优麓
- POJ3628:Bookshelf 2【01背包】
- 椒写昧还访闷仑蓟泳礁迟迟紊旱凡
- 梁衅衅兔约帕屡商览鞍浇烫排刎荚
- HDU 5044 Tree(LCA ,2014上海网络赛1003)
- Configure .htaccess
- c/c++函数调用的栈的问题
- HackerRank - Stock Maximize
- Binary Tree Inorder Traversal [leetcode] 非递归的三种解法
- WinForm下编写分页控件,实现DataGridView的分页效果
- SQL语句执行顺序
- zoj 2750 Idiomatic Phrases Game(最短路径)
- 【Java】StringTokenizer简单使用