题意:给你一颗树,每个结点的儿子数不超过2。每个结点有一个权值,一个结点的代价被定义为将其子树中所有结点的权值放入数组排序后,每个权值乘以其下标的和。让你计算所有结点的代价。

二叉树的条件没有用到。

每个结点开一个Splay,从叶子往上启发式合并上去,可以先bfs一遍确定合并顺序。每一次将Splay大小较小的结点的权值全提取出来塞到较大的里面。

由于权值可能重复出现,所以每个结点记个cnt。

答案统计的时候,就将那个刚塞进去的旋到根,然后答案加上左子树的权值和,再加上(右子树的权值的个数+该结点的cnt)*该结点的权值。

然后将较大儿子的Splay的根丢给父亲。

不必要进行内存回收,通过计算,所开的空间只要达到nlogn即可,实际上100w足够了。

#include<cstdio>
#include<set>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1000000;
ll sum[maxn];
int fa[maxn],val[maxn],c[maxn][2],root,tot,siz[maxn],cnt[maxn];
void Maintain(int x)
{
siz[x]=siz[c[x][0]]+siz[c[x][1]]+cnt[x];
sum[x]=sum[c[x][0]]+sum[c[x][1]]+(ll)val[x]*(ll)cnt[x];
}
void NewNode(int &x,int Fa,int key)
{
x=++tot;
fa[x]=Fa;
c[x][0]=c[x][1]=0;
val[x]=key;
siz[x]=cnt[x]=1;
}
void Rotate(int x,bool flag)
{
int y=fa[x];
c[y][!flag]=c[x][flag];
fa[c[x][flag]]=y;
if(fa[y]){
c[fa[y]][c[fa[y]][1]==y]=x;
}
fa[x]=fa[y];
c[x][flag]=y;
fa[y]=x;
Maintain(y);
Maintain(x);
}
void Splay(int &root,int x,int goal)
{
if(!x){
return;
}
int y;
while((y=fa[x])!=goal){
if(fa[y]==goal){
Rotate(x,c[y][0]==x);
}
else{
if((c[y][0]==x)==(c[fa[y]][0]==y)){
Rotate(y,c[fa[y]][0]==y);
}
else{
Rotate(x,c[y][0]==x);
y=fa[x];
}
Rotate(x,c[y][0]==x);
}
}
Maintain(x);
if(!goal){
root=x;
}
}
int Find(int key,int x)
{
while(c[x][val[x]<key]){
if(val[x]==key){
return x;
}
x=c[x][val[x]<key];
}
return x;
}
void Insert(int &root,int key)
{
int x=Find(key,root);
if(val[x]==key){
++cnt[x];
Splay(root,x,0);
return;
}
NewNode(c[x][val[x]<key],x,key);
Splay(root,c[x][val[x]<key],0);
} int roots[100005];
ll anss[100005];
bool vis[100005];
int e,first[100005],nex[200005],v[200005];
int dep[100005];
void AddEdge(int U,int V){
v[++e]=V;
nex[e]=first[U];
first[U]=e;
}
int T,n,a[100005],b[100005];
bool cmp(const int &a,const int &b){
return siz[roots[a]]>siz[roots[b]];
}
int sons[100005],BI;
void dfs(int U){
for(int i=1;i<=cnt[U];++i){
Insert(roots[sons[1]],val[U]);
int X=Find(val[U],roots[sons[1]]);
Splay(roots[sons[1]],X,0);
if(c[X][0]){
anss[BI]+=sum[c[X][0]];
}
anss[BI]+=(ll)(cnt[X]+(c[X][1] ? siz[c[X][1]] : 0))*(ll)val[U];
}
if(c[U][0]){
dfs(c[U][0]);
}
if(c[U][1]){
dfs(c[U][1]);
}
}
int main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d",&T);
int x,y;
for(;T;--T){
memset(first,0,sizeof(first));
e=0;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
for(int i=1;i<n;++i){
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
memset(vis,0,sizeof(vis));
memset(dep,0,sizeof(dep));
memset(anss,0,sizeof(anss));
queue<int>q;
q.push(1);
int t=0;
while(!q.empty()){
int U=q.front(); q.pop(); vis[U]=1;
b[++t]=U;
for(int i=first[U];i;i=nex[i]){
if(!vis[v[i]]){
dep[v[i]]=dep[U]+1;
q.push(v[i]);
}
}
}
for(int i=t;i>=1;--i){
BI=b[i];
int dir_son=0;
for(int j=first[b[i]];j;j=nex[j]){
if(dep[v[j]]>dep[b[i]]){
sons[++dir_son]=v[j];
}
}
if(!dir_son){
NewNode(roots[b[i]],0,a[b[i]]);
anss[b[i]]=a[b[i]];
continue;
}
sort(sons+1,sons+dir_son+1,cmp);
anss[b[i]]=anss[sons[1]];
for(int j=2;j<=dir_son;++j){
dfs(roots[sons[j]]);
}
Insert(roots[sons[1]],a[b[i]]);
int X=Find(a[b[i]],roots[sons[1]]);
Splay(roots[sons[1]],X,0);
if(c[X][0]){
anss[BI]+=sum[c[X][0]];
}
anss[BI]+=(ll)(cnt[X]+(c[X][1] ? siz[c[X][1]] : 0))*(ll)a[b[i]];
roots[b[i]]=roots[sons[1]];
}
for(int i=1;i<=n;++i){
printf("%lld ",anss[i]);
}
puts("");
memset(sum,0,sizeof(ll)*(tot+1));
memset(fa,0,sizeof(int)*(tot+1));
memset(val,0,sizeof(int)*(tot+1));
for(int i=0;i<=tot;++i){
c[i][0]=c[i][1]=0;
}
memset(siz,0,sizeof(int)*(tot+1));
memset(cnt,0,sizeof(int)*(tot+1));
memset(roots,0,sizeof(int)*(tot+1));
// printf("%d\n",tot);
tot=0;
}
return 0;
}

【Splay】【启发式合并】hdu6133 Army Formations的更多相关文章

  1. 【BZOJ-2809】dispatching派遣 Splay + 启发式合并

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2334  Solved: 1192[Submi ...

  2. 【BZOJ-2733】永无乡 Splay+启发式合并

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2048  Solved: 1078[Submit][Statu ...

  3. BZOJ2733 永无乡【splay启发式合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  5. bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

    这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...

  6. 【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)

    题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被 ...

  7. 算法复习——splay+启发式合并(bzoj2733-永无乡)

    题目: Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通 ...

  8. 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并

    启发式合并而已啦,, 调试时发现的错误点:insert后没有splay,把要拆开的树的点插入另一个树时没有把ch[2]和fa设为null,找第k大时没有先减k,,, 都是常犯的错误,比赛时再这么粗心就 ...

  9. 【BZOJ2809】【splay启发式合并】dispatching

    Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...

随机推荐

  1. Fermat2018游记

    day (-22) 2018年2月5日 Devin大佬给我发了一份Waterloo AIF的原件截图,发现里面居然直接问你的Fermat分数,那么这么重要的考试当然不能错过啊 若干天之后刚开学不久的一 ...

  2. bootstrap 弹窗 数据清除

    bootstrap modal操作简单易用, //清除弹窗原数据 $("#create_modal").on("hidden.bs.modal", functi ...

  3. markdown===在新窗口中打开网址的解决办法,以及其他遗留问题!

    [超链接文字](url){:target="_blank"} 遗留问题: 如何设置图片的尺寸 我的复选框一直不生效,why? 公式 $$ 公式 $$ 不生效 如何设置代码块的背景颜 ...

  4. 实验室项目.md

    1 嵌入式操作系统 为什么要用嵌入式操作系统 普通的单片机编程:程序(软件)--单片机硬件: 嵌入式操作系统开发:程序(软件)--操作系统--嵌入式硬件(包括单片机等); 我们平时普通所学的单片机编程 ...

  5. 微信支付之SHA256签名失败

    在接微信支付的时候,或多或少会遇到签名失败,本人接入的时候也遇了不少次: 总结如下: 1.参数没有经过ASCII排序 2.参数包含中文未经过UTF-8标准转化加密后的签名不对应(经本人测验:加密算法要 ...

  6. JVM对象分配和GC分布【JVM】

    最近在学习java基础结构,刚好学到了jvm,总结了以下并可以结合思维导图认识以下Jvm的对象: 栈:什么是栈? 先说一下栈的数据结构吧,栈它是一种先进后出的数据结构(FILO),跟队列刚好相反(先进 ...

  7. Spring,tk-mapper源码阅读

    Mybatis的源码学习(一): 前言: 结合spring本次学习会先从spring-mybatis开始分析 在学习mybatis之前,应该要对spring的bean有所了解,本文略过 先贴一下myb ...

  8. 怎么快速入门一个老的java项目

    作者:eilen著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1.有文档肯定先看文档,先看设计文档,产品的.技术的设计文档,接口文档写的好的可以看看,要是写的不好不着急看. 2 ...

  9. Vim配置Node.js开发工具

    ubuntu安装vim编辑器.默认情况下,vim在运行的时候会加载-/.vimrc文件里的配置文件,如果在-目录下不存在这个配置文件可以手动创建. 在-/.vim目录下是vim的插件加载的位置,可以在 ...

  10. [ python ] 项目一:FTP程序

    声明: 该项目参考学习地址: http://www.cnblogs.com/lianzhilei/p/5869205.html , 感谢博主分享,如有侵权,立即删除. 作业:开发一个支持多用户在线的F ...