zoukankan      html  css  js  c++  java
  • 【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);
    }
  • 相关阅读:
    DevEco Studio常用设置
    idea报错:Failed to execute goal org.codehaus.mojo:execmavenplugin:3.0.0:exec (defaultcli) on
    HarmonyOS实战 — 第一个入门 HelloWorld
    RabbitMQ入门之HelloWorld
    鸿蒙系统简介
    阿里云短信验证出现签名不合法(不存在或被拉黑)
    鸿蒙和安卓的对比
    关于 SVN 没有加锁 却在 update 和 commit 时 提示 有锁
    ibatis xml 数据库 批量新增 与批量删除
    看不懂的类型转换(有待解决)
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11427174.html
Copyright © 2011-2022 走看看