HDU - 6133 启发式合并
题意:给出一棵树共\(n\)个顶点,每个顶点有一个权值\(val_i\),你需要对每个节点统计一个最优解
每个节点的解按照一定规则产生:取出该节点的子树下所有的顶点,把顶点任意排序成一个序列,设为\(v_1,v_2...,v_k\)
此时解为\(\sum_{i=1}^{k}\sum_{j=1}^{i}val_{v_j}\),最小的解为最优解
对于每个解的处理来说,子树下值小的顶点肯定放前面,按这样来贪心无疑是正确的(前缀贡献尽量小)
那么对于无序的插入过程,当前节点\(u\)的贡献为\(val_u+cnt+num*val_u\)
其中\(cnt\)为当前小于\(val_u\)的数字和,\(num\)为当前大于等于\(val_u\)的个数和
因为是子树问题,用树状数组暴力合并答案,复杂度\(O(nlog^2n)\)
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)a)
#define printbk(a) printf("%lld ",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 2e6+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll a[MAXN],b[MAXN],c[MAXN];
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
struct FT{
ll ft[MAXN];
int tot;
void init(int t){for(tot=t=t<<1|1;t;--t)ft[t]=0;}
#define lowbit(x) (x&-x)
void update(int k,int v){while(k<tot)ft[k]+=v,k+=lowbit(k);}
ll query(int k){return k>0?ft[k]+query(k-lowbit(k)):0;}
}ft[2];
int size[MAXN],son[MAXN],st[MAXN],ed[MAXN],pre[MAXN],CLOCK;
void init(){
memset(head,-1,sizeof head);
tot=CLOCK=0;
}
void dfs(int u,int fa){
size[u]=1;son[u]=0;
st[u]=++CLOCK;pre[CLOCK]=u;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
dfs(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
ed[u]=CLOCK;
}
ll ans[MAXN];
void solve(int u,int fa,bool keep){
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
if(v==son[u]) continue;
solve(v,u,0);
}
if(son[u]) solve(son[u],u,1);
ll t=ans[son[u]];
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
if(v==son[u]) continue;
rep(j,st[v],ed[v]){
t+=a[pre[j]];
t+=ft[0].query(c[pre[j]]-1);
ft[0].update(c[pre[j]],a[pre[j]]);
t+=(ft[1].query(ft[1].tot)-ft[1].query(c[pre[j]]-1))*a[pre[j]];
ft[1].update(c[pre[j]],1);
}
}
t+=a[u];
t+=ft[0].query(c[u]-1);
ft[0].update(c[u],a[u]);
t+=(ft[1].query(ft[1].tot)-ft[1].query(c[u]-1))*a[u];
ft[1].update(c[u],1);
ans[u]=t;
if(!keep) rep(j,st[u],ed[u]){
ft[0].update(c[pre[j]],-a[pre[j]]);
ft[1].update(c[pre[j]],-1);
}
}
int main(){
int T=read();
while(T--){
int n=read();
rep(i,1,n) b[i]=a[i]=read();
sort(b+1,b+1+n);
int m=unique(b+1,b+1+n)-b-1;
rep(i,1,n) c[i]=lower_bound(b+1,b+1+n,a[i])-b;
rep(i,0,1) ft[i].init(max(n,m));
init();
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
memset(ans,0,sizeof ans);
dfs(1,-1);
solve(1,-1,1);
rep(i,1,n) printbk(ans[i]); puts("");
}
return 0;
}
HDU - 6133 启发式合并的更多相关文章
- hdu 3371(启发式合并的最小生成树)
Connect the Cities Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 Problem Description The soil is cracking up beca ...
- [HDU 3712] Fiolki (带边权并查集+启发式合并)
[HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...
- 数据结构(trie,启发式合并):HDU 5841 Alice and Bob
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABJEAAAE6CAIAAAApz1RvAAAgAElEQVR4nO3d3css1b3g8fyTdbHJbD
- hdu 6133---Army Formations(启发式合并+树状数组)
题目链接 Problem Description > Stormtroopers were the assault/policing troops of the Galactic Empire. ...
- HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Tota ...
- Problem E. TeaTree - HDU - 6430 (树的启发式合并)
题意 有一棵树,每个节点有一个权值. 任何两个不同的节点都会把他们权值的\(gcd\)告诉他们的\(LCA\)节点.问每个节点被告诉的最大的数. 题解 第一次接触到树的启发式合并. 用一个set维护每 ...
- HDU - 4358 Boring counting (树上启发式合并/线段树合并)
题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> usin ...
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
随机推荐
- 健康类App原型制作分享-Mindmate
Mindmate是一款健康类App,主要是帮助人们快速入眠,放松情绪,它拥有小清新的界面,配图全是由插画组成,生动有趣.在这款原型中,为了保持App的原有特色,将插画通过图片组件导入进来:音乐播放界面 ...
- 使用JFinal框架连接数据库,实现注册、登录功能
使用JFinal框架连接数据库,实现注册.登录功能 1.在Eclipse中新建Dynamic Web project项目 2.导入jfinal-2.2-bin-with-src.jar.c3p0-0. ...
- HTML5 桌面消息提醒
Notification HTML5新属性,复制代码创建HTML文件,浏览器查看效果 <!DOCTYPE html> <html lang="en"> &l ...
- 企业搜索引擎开发之连接器connector(二十八)
通常一个SnapshotRepository仓库对象对应一个DocumentSnapshotRepositoryMonitor监视器对象,同时也对应一个快照存储器对象,它们的关联是通过监视器管理对象D ...
- 汉诺塔问题的算法分析与实现(Java)
汉诺塔问题是源于印度一个古老传说的益智玩具.要求将圆盘从A柱移动到C柱规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘. 可以先通过3个盘子的hanoi游戏得出其算法步骤如下: if ...
- firedac odbc sql server driver连接占线导致另一个hstmt
firedac odbc sql server driver连接占线导致另一个hstmt 原因:FDQuery.FetchOptions.Mode=fmOnDemand.好像是为了性能问题,不设置则默 ...
- Snapshot--使用Snapshot来还原数据库
在数据库升级时,为防止升级失败造成的影响,我们通常需要: 1.准备回滚脚本,用于失败后回滚 2.在升级前备份数据库,用于失败后恢复 但回滚脚本需要花费很长时间准备,而备份恢复会导致数据库长时间不可用, ...
- 简易网页 html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 总结目前为止学到的关键字(break,continue,private,static,this,super,final,abstract)
1.控制跳转语句:break(结束) 使用的场景: a.循环当中 b.switch break关键字需要注意的问题: 1.break关键字只能用于循环和switch语句当中,其本质就是结束整段语句的意 ...
- 流式处理框架storm浅析(下篇)
本文来自网易云社区 作者:汪建伟 举个栗子 1 实现的目标 设计一个系统,来实现对一个文本里面的单词出现的频率进行统计. 2 设计Topology结构: 这是一个简单的例子,topology也非常简单 ...