Processing math: 100%

【AHOI2018】排列

题面

https://www.luogu.org/problem/P4437

题解

先把依赖关系形成的数建出来。

化一下那个式子,再作差比较一下,发现就是找平均值最大的一段。

然后用线段树维护最大值和单点修改(删除操作),删除一个点就直接把他的儿子接到它父亲上。

细节记得不太清楚了。

复制代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define ri register int
#define N 500050
#define ll long long
#define inf 987654321*987654321LL
using namespace std;

int n;
ll w[N],tot[N],a[N],fa[N],siz[N];
bool used[N],del[N];
vector<ll> back[N];

struct segment_tree{
  ll tt[4*N];
  void maketree(int x,int l,int r){
    if (l==r) {
      tt[x]=l;
      return;
    }
    int mid=(l+r)>>1;
    maketree(x<<1,l,mid); maketree(x<<1|1,mid+1,r);
    if (w[tt[x<<1]]<=w[tt[x<<1|1]]) tt[x]=tt[x<<1]; else tt[x]=tt[x<<1|1];
  }
  int query() {
    return tt[1];
  }
  void update(int x,int loc,int l,int r) {
    if (l==r) {
      tt[x]=l;
      return;
    }
    int mid=(l+r)>>1;
    if (loc<=mid) update(x<<1,loc,l,mid); else update(x<<1|1,loc,mid+1,r);
    if (w[tt[x<<1]]/((long double)siz[tt[x<<1]])<w[tt[x<<1|1]]/((long double)siz[tt[x<<1|1]]*1.0))
      tt[x]=tt[x<<1]; else tt[x]=tt[x<<1|1];
  }
} yy;

int main() {
  scanf("%d",&n);
  for (ri i=1;i<=n;i++) {
    scanf("%lld",&a[i]);
    if (a[i]) {
      back[a[i]].push_back(i);
      fa[i]=a[i];
    }
  }
  for (ri i=1;i<=n;i++) {
    scanf("%lld",&w[i]);
    tot[i]=w[i];
    siz[i]=1;
  }
  ll ans=0,cnt=0;
  yy.maketree(1,1,n);
  for (ri i=1;i<=n;i++) used[i]=0;
  used[0]=1;
  for (ri i=1;i<=n;i++) {
    int now=yy.query();
    if (used[fa[now]]) {
      ans+=cnt*w[now]+tot[now];
      cnt+=siz[now];
      used[now]=1;
      w[now]=inf;
      siz[now]=1;
      yy.update(1,now,1,n);
    }
    else {
      del[now]=1;
      for (ri j=back[now].size()-1;j>=0;j--) if (!del[back[now][j]])fa[back[now][j]]=fa[now],back[fa[now]].push_back(back[now][j]);
      tot[fa[now]]=tot[fa[now]]+siz[fa[now]]*w[now]+tot[now];
      siz[fa[now]]+=siz[now];
      w[fa[now]]+=w[now];
      yy.update(1,fa[now],1,n);
      w[now]=inf;
      siz[now]=1;
      yy.update(1,now,1,n);
    }
  }
  if (ans==0) puts("-1"); else printf("%lld",ans);
}
复制代码

 

posted @   HellPix  阅读(143)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!
点击右上角即可分享
微信分享提示