HDU 6133 Army Formations(2017 Multi-University Training Contest 8)
2017-08-18 12:57
302 查看
题目链接:Army Formations
题意:一棵二叉树,每一个节点有一个信息ai,每发送一个信息需要的时间是当前时间t加上这个信息的权值ai,问从每一个节点出发,发送完以这个节点作为根节点的子树中的所有信息所需要的最小时间。
题解:显然,如果我们把一个权值大的放在前面,所有在这个信息后面的信息所需要的时间都会增加,于是我们贪心的发送,即按照权值从小到大发送就是最优方法。那么问题就变成了,我们如何算出子树内每一个节点子树和排序后的前缀和的和。由于我们需要快速合并两棵子树的权值,很容易想到用树状数组即可,同时维护一个current_ans来记录当前的答案。整个操作流程就是:
以上代码来自官方题解。
为了保证合并的快速,所以我们需要启发式合并,即把小的子树合并到大的子树中,合并过程中每一个元素最多被合并log次,而树状数组插入的时间复杂度是O(log n),于是整个算法的时间复杂度就是O(nlog2n)。
注意由于要大量调用递归函数,所以一个参数会比两个参数的函数快很多,我被这个地方卡了一上午= =
题意:一棵二叉树,每一个节点有一个信息ai,每发送一个信息需要的时间是当前时间t加上这个信息的权值ai,问从每一个节点出发,发送完以这个节点作为根节点的子树中的所有信息所需要的最小时间。
题解:显然,如果我们把一个权值大的放在前面,所有在这个信息后面的信息所需要的时间都会增加,于是我们贪心的发送,即按照权值从小到大发送就是最优方法。那么问题就变成了,我们如何算出子树内每一个节点子树和排序后的前缀和的和。由于我们需要快速合并两棵子树的权值,很容易想到用树状数组即可,同时维护一个current_ans来记录当前的答案。整个操作流程就是:
def tree_remove(root): for x in tree(root): remove_from_multiset(x) def tree_add(root): for x in tree(root): add_into_multiset(x) def dfs(root): dfs(left_son) tree_remove(left_son) dfs(right_son) tree_add(left_son) add_into_multiset(root) f[root] = ask_sumofsum()
以上代码来自官方题解。
为了保证合并的快速,所以我们需要启发式合并,即把小的子树合并到大的子树中,合并过程中每一个元素最多被合并log次,而树状数组插入的时间复杂度是O(log n),于是整个算法的时间复杂度就是O(nlog2n)。
注意由于要大量调用递归函数,所以一个参数会比两个参数的函数快很多,我被这个地方卡了一上午= =
#include <iostream> #include <stdio.h> #include <vector> #include <algorithm> using namespace std; const int N = 100005; long long c1 ,c2 ,ans ,t; int b ,v ,id ,sz ,ls ,rs ,ed; vector<int>e ; void Add(long long* wh,int i,int d){ for(;i<N;i+=i&-i) wh[i]+=d; } long long Sum(long long* wh,int i){ long long res=0; for(;0<i;i-=i&-i) res+=wh[i]; return res; } int dfs1(int last,int now){ sz[now]=1; for(int i=0;i<e[now].size();i++) if(e[now][i]!=last){ if(ls[now]==-1) ls[now]=e[now][i]; else if(rs[now]==-1) rs[now]=e[now][i]; sz[now]+=dfs1(now,e[now][i]); } if(rs[now]!=-1&&sz[ls[now]]>sz[rs[now]]) swap(ls[now],rs[now]); return sz[now]; } void Plu(int x){ t+=(Sum(c1,ed)-Sum(c1,id[x]-1)+1)*v[x]+Sum(c2,id[x]-1); Add(c1,id[x],1); Add(c2,id[x],v[x]); } void Miu(int x){ t-=(Sum(c1,ed)-Sum(c1,id[x]-1))*v[x]+Sum(c2,id[x]-1); Add(c1,id[x],-1); Add(c2,id[x],-v[x]); } void Pls(int now){ Plu(now); if(ls[now]!=-1) Pls(ls[now]); if(rs[now]!=-1) Pls(rs[now]); } void Sub(int now){ Miu(now); if(ls[now]!=-1) Sub(ls[now]); if(rs[now]!=-1) Sub(rs[now]); } void dfs2(int now){ if(ls[now]!=-1) dfs2(ls[now]); if(rs[now]!=-1){ Sub(ls[now]); dfs2(rs[now]); Pls(ls[now]); } Plu(now); ans[now]=(ls[now]==-1&&rs[now]==-1?v[now]:t); } int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ e[i].clear(); ls[i]=rs[i]=-1; scanf("%d",&v[i]); b[i]=v[i]; } sort(b+1,b+1+n); ed=unique(b+1,b+1+n)-(b+1); for(int i=1;i<=ed;i++) c1[i]=c2[i]=0; for(int i=1;i<=n;i++) id[i]=lower_bound(b+1,b+ed,v[i])-b; for(int i=1,x,y;i<n;i++){ scanf("%d %d",&x,&y); e[x].push_back(y); e[y].push_back(x); } dfs1(0,1); t=0; dfs2(1); for(int i=1;i<=n;i++) printf("%lld ",ans[i]); puts(""); } return 0; }
相关文章推荐
- HDU 6133 Army Formations (树状数组, 2017 Multi-Univ Training Contest 8)
- HDU 6038 Function(找规律)——2017 Multi-University Training Contest - Team 1
- hdu 6034 Balala Power!(贪心)( 2017 Multi-University Training Contest - Team 1 )(无耻之sort)
- hdu 6047 Maximum Sequence(2017 Multi-University Training Contest - Team 2)
- hdu 6045 Is Derek lying?(2017 Multi-University Training Contest - Team 2)
- HDU - 6105 Gameia(必胜策略)(2017 Multi-University Training Contest - Team 6)
- hdu 6055 Regular polygon(判断正方形)(2017 Multi-University Training Contest - Team 2)
- hdu 6045 简单的思维题 2017 Multi-University Training Contest - Team 2
- HDU 6050 - Funny Function | 2017 Multi-University Training Contest 2
- HDU_【2017 Multi-University Training Contest 2】——1008 To my boyfriend
- 2017 Multi-University Training Contest 10 1010 Schedule && HDU 6180 (贪心)
- 2017 Multi-University Training Contest 3( hdu 6060) RXD and dividing
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- HDU 6059 - Kanade's trio | 2017 Multi-University Training Contest 3
- HDU 6086 Rikka with String(2017 Multi-University Training Contest 3)
- hdu 6069 Counting Divisors(约数个数)(2017 Multi-University Training Contest - Team 4 )
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- hdu 6071 Lazy Running(优先队列+dijkstra)(2017 Multi-University Training Contest - Team 4)
- HDU-6140 Killer Names - 2017 Multi-University Training Contest - Team 8(思维)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )