题意:给出一棵树共\(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 启发式合并的更多相关文章

  1. hdu 3371(启发式合并的最小生成树)

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  2. 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 ...

  3. [HDU 3712] Fiolki (带边权并查集+启发式合并)

    [HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...

  4. 数据结构(trie,启发式合并):HDU 5841 Alice and Bob

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABJEAAAE6CAIAAAApz1RvAAAgAElEQVR4nO3d3css1b3g8fyTdbHJbD

  5. hdu 6133---Army Formations(启发式合并+树状数组)

    题目链接 Problem Description > Stormtroopers were the assault/policing troops of the Galactic Empire. ...

  6. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

  7. Problem E. TeaTree - HDU - 6430 (树的启发式合并)

    题意 有一棵树,每个节点有一个权值. 任何两个不同的节点都会把他们权值的\(gcd\)告诉他们的\(LCA\)节点.问每个节点被告诉的最大的数. 题解 第一次接触到树的启发式合并. 用一个set维护每 ...

  8. HDU - 4358 Boring counting (树上启发式合并/线段树合并)

    题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> usin ...

  9. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

随机推荐

  1. ie高版本浏览器不支持velocity的问题解决

    <head><meta http-equiv="X-UA-Compatible" content="IE=5"></head> ...

  2. velocity在html中换行符转换

    <td colspan="3" class="tdContent2">$!obj.getDealInfo().replaceAll("\r ...

  3. IntelliJ IDEA 2017版开发SpringBoot之fastJsonHttpMessageConvert使用

    继承WebMvcConfigurerAdapter,改写成自己的json转换工具的写法 1.建立实体类 package com.fastjson; import com.alibaba.fastjso ...

  4. 一条java开发工程师的升级路线,从初级到无语言障碍

    看了一篇文章,讲述的是如何进行后端开发升级,现在分享下,我的总结,感谢写文章的作者大大,觉得他很会坚持,虽然一直在骂人,但是,我觉得人最大的敌人就是懒惰,所以骂得好 现在写下我的总结,希望对有志者有帮 ...

  5. Java 代理模式(二) Java中的动态代理

    动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Objec ...

  6. Scala程序编译运行

    1.编译 Scala演示代码如下: <pre name="code" class="plain">/** * @author Administrat ...

  7. 怎样运用servlet

    制作登陆界面 login.html <!DOCTYPE html> <html> <head> <title>login.html</title& ...

  8. Android-自定义圆环

    效果图: 布局的代码,指定引用自定义View类: <!-- 绘制圆环 --> <LinearLayout xmlns:android="http://schemas.and ...

  9. TSQL--TOP选项

    TOP选项需要依据ORDER来选取记录,可以依据行数和百分比来选取记录 按照行数来选取10行记录 SELECT TOP(10) * FROM T1 ORDER BY ID 按照行数来选取10%的记录 ...

  10. CheckBox使用记录

    页面显示 页面代码 <div> <div><input type="checkbox" value="" class=" ...