题面传送门

开始 WA ycx 的遗产(bushi

首先可以将题目转化为图论模型:\(\forall i\) 连边 \(a_i\to i\),然后求图的一个拓扑序 \(b_1,b_2,\dots b_n\) 使得 \(\sum\limits_{i=1}^niw_{b_i}\) 最小。显然如果原图出现环就 \(-1\) 了。否则原图一定是一棵森林。

然后我就在那儿想各种乱搞,包括但不限于 DP、贪心之类,然后都假掉了

我们知道有个东西叫排序不等式,它是说 \(\forall a_1\leq a_2\leq a_3\leq\dots\leq a_n,b_1\leq b_2\leq b_3\leq\dots\leq b_n\) 都有 \(\sum\limits_{i=1}^na_ib_i\geq\sum\limits_{i=1}^na_ib_{p_i}\geq\sum\limits_{i=1}^na_ib_{n-i+1}\),其中 \(p\) 为 \(1\sim n\) 的任意一个排列。

将排序不等式应用于此题。如果设 \(a_i=i\),\(b\) 为 \(w\) 排好序的结果可得理论最大值为 \(\sum\limits_{i=1}^nib_i\)。换句话说,假设使 \(w_i\) 取到最小值的 \(i\) 为 \(x\),那么我们肯定贪心地想把 \(x\) 放在前面,越靠前越好。

不过问题是,\(a_x\) 不一定等于 \(0\),也就是说 \(x\) 不一定有能力成为拓扑序的第一个元素。这时候该怎么办呢?我们不考虑现在,我们考虑未来。我们定义当前状态下的“可选集合”为满足 \(a_x=0\) 或者 \(a_x\) 已经被加入拓扑序的 \(x\) 的集合,也就是说可选集合内的元素都可以成为拓扑序中的下一个元素。考虑什么时候 \(x\) 能够进入可选集合。显然要当 \(a_x\) 已经被加入拓扑序之后。而根据之前的推论我们肯定希望 \(x\) 越靠前越好,也就是说一旦 \(a_x\) 被加入拓扑序,我们就令 \(x\) 为拓扑序中下一个元素,相当于将 \(a_x\) 与 \(x\) 捆绑在了一起。

P.S:如果你对为什么 \(x\) 越靠前越好的证明感兴趣的话,可以从这里往下看:

假设 \(a_x\) 是第 \(s\) 个加入拓扑序的,\(x\) 是第 \(t(t>s+1)\) 个加入拓扑序的,第 \(i\) 个加入拓扑序的元素为 \(b_{i}\),那么我们显然有代价为 \(\sum\limits_{i=1}^siw_{b_i}+\sum\limits_{i=1}^{t-s-1}(s+i)w_{b_{i+s}}+tw_x+\sum\limits_{i=t+1}^niw_{b_i}\)

而倘若我们将第 \(x\) 个元素加入拓扑序的时间提前到 \(s+1\),其他元素加入拓扑序的时间保持不变,那么代价变为 \(\sum\limits_{i=1}^siw_{b_i}+(s+1)w_x+\sum\limits_{i=1}^{t-s-1}(s+i+1)w_{b_i+s}+\sum\limits_{i=t+1}^niw_{b_i}\)

二者做差可得 \(\Delta=\sum\limits_{i=1}^{t-s-1}w_{b_i+s}-(t-s-1)w_x\)

根据 \(w_x\) 为 \(\min\{w_i\}\) 可知 \(\dfrac{\sum\limits_{i=1}^{t-s-1}w_{b_i+s}}{t-s-1}\geq w_x\),换句话说,任意 \(t-s-1\) 个 \(w_i\) 的平均值 \(\geq w_x\)。

故 \(\Delta\geq 0\)。而显然将第 \(x\) 个元素加入拓扑序的时间提前到 \(s+1\) 依旧合法。故我们选择 \(x\) 越靠前越好。

还有一个问题,就是经过若干次合并后树上的每一个元素都是一个合并序列,也就是若干个形如 \(t_1,t_2,\dots t_m\),其中 \(t_i\) 拓扑序下一个必须是 \(t_{i+1}\) 的序列。此时我们就要探究合并序列的大小关系,考虑两个序列 \(x_1,x_2,\dots x_p\) 和 \(y_1,y_2,\dots,y_q\) 合并的大小关系。

  • 若 \(x\) 合并到 \(y\) 前面,\(W=\sum\limits_{i=1}^piw_{x_i}+\sum\limits_{i=1}^q(i+p)w_{y_i}\)
  • 若 \(y\) 合并到 \(x\) 前面,\(W=\sum\limits_{i=1}^qiw_{y_i}+\sum\limits_{i=1}^p(i+q)w_{x_i}\)

二者做差可得 \(\Delta=-q\times\sum\limits_{i=1}^pw_{x_i}+p\times\sum\limits_{i=1}^qw_{y_i}\)

我们不妨假设 \(\Delta\geq 0\),不等号两边同除 \(pq\) 可得 \(-\dfrac{\sum\limits_{i=1}^pw_{x_i}}{p}+\dfrac{\sum\limits_{i=1}^qw_{y_i}}{q}\geq 0\)。

即 \(\dfrac{\sum\limits_{i=1}^qw_{y_i}}{q}\geq \dfrac{\sum\limits_{i=1}^pw_{x_i}}{p}\)

也就是说我们选择将平均值大的序列合并到平均值小的序列的后面。

用堆维护即可。

复杂度线性对数。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define fi first
  4. #define se second
  5. #define fill0(a) memset(a,0,sizeof(a))
  6. #define fill1(a) memset(a,-1,sizeof(a))
  7. #define fillbig(a) memset(a,63,sizeof(a))
  8. #define pb push_back
  9. #define ppb pop_back
  10. #define mp make_pair
  11. template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
  12. template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
  13. typedef pair<int,int> pii;
  14. typedef long long ll;
  15. typedef unsigned int u32;
  16. typedef unsigned long long u64;
  17. namespace fastio{
  18. #define FILE_SIZE 1<<23
  19. char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
  20. inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
  21. inline void putc(char x){(*p3++=x);}
  22. template<typename T> void read(T &x){
  23. x=0;char c=getchar();T neg=0;
  24. while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
  25. while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
  26. if(neg) x=(~x)+1;
  27. }
  28. template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
  29. template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
  30. void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
  31. }
  32. const int MAXN=5e5;
  33. int n,a[MAXN+5],b[MAXN+5],vis[MAXN+5];
  34. void dfs(int x){
  35. if(!(vis[x]^2)) puts("-1"),exit(0);
  36. if(!(vis[x]^1)) return;vis[x]=2;
  37. if(a[x]) dfs(a[x]);vis[x]=1;
  38. }
  39. int f[MAXN+5],siz[MAXN+5];ll sum[MAXN+5],val[MAXN+5];
  40. int getf(int x){return (!~f[x])?x:f[x]=getf(f[x]);}
  41. void merge(int x,int y){
  42. x=getf(x);y=getf(y);
  43. f[y]=x;sum[x]+=sum[y];
  44. val[x]+=val[y]+1ll*sum[y]*siz[x];
  45. siz[x]+=siz[y];
  46. // printf("merge %d %d %d %lld %lld\n",x,y,siz[x],sum[x],val[x]);
  47. }
  48. struct frac{
  49. ll x,y;
  50. frac(ll _x=0,ll _y=1):x(_x),y(_y){}
  51. bool operator <(const frac &rhs) const{
  52. return x*rhs.y<rhs.x*y;
  53. }
  54. };
  55. set<pair<frac,int> > st;
  56. int main(){
  57. scanf("%d",&n);
  58. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  59. for(int i=1;i<=n;i++) scanf("%d",&b[i]);
  60. for(int i=1;i<=n;i++) dfs(i);f[0]=-1;
  61. for(int i=1;i<=n;i++) f[i]=-1,siz[i]=1,sum[i]=val[i]=b[i];
  62. for(int i=1;i<=n;i++) st.insert(mp(frac(b[i],1),i));
  63. while(!st.empty()){
  64. pair<frac,int> pp=*st.begin();st.erase(st.begin());
  65. int id=pp.se,f1=getf(id),f2=getf(a[f1]);
  66. if(f2) st.erase(st.find(mp(frac(sum[f2],siz[f2]),f2)));
  67. merge(f2,f1);if(f2) st.insert(mp(frac(sum[f2],siz[f2]),f2));
  68. } printf("%lld\n",val[0]);
  69. return 0;
  70. }

洛谷 P4437 [HNOI/AHOI2018]排列(贪心+堆,思维题)的更多相关文章

  1. [Bzoj5285][洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)

    P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生 ...

  2. [HNOI/AHOI2018]排列 贪心

    题面 题解: 把题面的限制换成中文: 如果排在第k位的下标 = 排在第j位的值 ,那么k < j 换一个描述方式: 一个值为x的数要排在第x个数后面. 再换一个描述方式: \(fa[i] = a ...

  3. 洛谷P4438 [HNOI/AHOI2018]道路(dp)

    题意 题目链接 Sol 每当出题人想起他出的HNOI 2018 Day2T3,他都会激动的拍打着轮椅 读题比做题用时长系列... \(f[i][a][b]\)表示从根到\(i\)的路径上,有\(a\) ...

  4. luogu P4437 [HNOI/AHOI2018]排列

    luogu 问题本质是把\(a_i\)作为\(i\)的父亲,然后如果有环就不合法,否则每次要取数,要满足取之前他的父亲都被取过(父亲为0可以直接取),求最大价值 贪心想法显然是要把权值大的尽量放在后面 ...

  5. 洛谷P4425 [HNOI/AHOI2018]转盘(线段树)

    题意 题目链接 Sol 首先猜一个结论:对于每次询问,枚举一个起点然后不断等到某个点出现时才走到下一个点一定是最优的. 证明不会,考场上拍了3w组没错应该就是对的吧... 首先把数组倍长一下方便枚举起 ...

  6. 洛谷P4424 [HNOI/AHOI2018]寻宝游戏(思维题)

    题意 题目链接 Sol 神仙题Orz Orz zbq爆搜70.. 考虑"与"和"或"的性质 \(0 \& 0 = 0, 1 \& 0 = 0\) ...

  7. [洛谷P4436] HNOI/AHOI2018 游戏

    问题描述 一次小G和小H在玩寻宝游戏,有n个房间排成一列,编号为1,2,...,n,相邻的房间之间都有一道门.其中一部分门上锁(因此需要有对应的钥匙才能开门),其余的门都能直接打开.现在小G告诉了小H ...

  8. 洛谷 P4426 - [HNOI/AHOI2018]毒瘤(虚树+dp)

    题面传送门 神仙虚树题. 首先考虑最 trival 的情况:\(m=n-1\),也就是一棵树的情况.这个我相信刚学树形 \(dp\) 的都能够秒掉罢(确信).直接设 \(dp_{i,0/1}\) 在表 ...

  9. 【LG4437】[HNOI/AHOI2018]排列

    [LG4437][HNOI/AHOI2018]排列 题面 洛谷 题解 题面里这个毒瘤的东西我们转化一下: 对于\(\forall k,j\),若\(p_k=a_{p_j}\),则\(k<j\). ...

随机推荐

  1. kivy画板

    from kivy.app import App from kivy.graphics import Line, Color # 引入绘图线条,颜色 from kivy.uix.widget impo ...

  2. 异常大讨论-抛出异常还是返回false

    iteye精华帖之异常大讨论 原帖链接http://www.iteye.com/topic/2038 Robbin的观点 观点1:Exception实际上代表了一个UseCase中的异常流的处理. 绝 ...

  3. virtual box搭建虚拟机nat和host only网络配置实用

    virtual box搭建虚拟机nat和host only网络配置实用 一.背景 二.需求 二.设置虚拟机的网络 1.创建一个全局的nat网络 2.添加主机网络管理器 3.设置虚拟机网络 1.网卡1设 ...

  4. (六)、Docker 之 Dockerfile

    1.什么是Dockerfile Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本. 2.Dockerfile解析过程 前提认知: 每条保留字指令都必须为大写字母 ...

  5. 搬运2:早期写的探究printf

    目录: 1. 关于printf格式化输出 2. printf的一般形式 3. 转换说明 4. 格式化输出的意义 5. 转换说明修饰符 6. 修饰符中的标记 7. printf的返回值 ps:共3250 ...

  6. C语言链表实例--玩转链表

    下图为最一简单链表的示意图: 第 0 个结点称为头结点,它存放有第一个结点的首地址,它没有数据,只是一个指针变量.以下的每个结点都分为两个域,一个是数据域,存放各种实际的数据,如学号 num,姓名 n ...

  7. Windows内核基础知识-5-调用门(32-Bit Call Gate)

    Windows内核基础知识-5-调用门(32-Bit Call Gate) 调用门有一个关键的作用,就是用来提权.调用门其实就是一个段. 调用门: 这是段描述符的结构体,里面的s字段用来标记是代码段还 ...

  8. 前端需要了解的颜色模型,RGB、HSL和HSV

    颜色模型,是用来表示颜色的数学模型.比如最常见的 RGB模型,使用 红绿蓝 三色来表示颜色. 一般的颜色模型,可以按照如下分类: 面向硬件设备的颜色模型:RGB,CMYK,YCrCb. 面向视觉感知的 ...

  9. 基于eNSP的NAT/NAPT协议仿真实践

    一. 基本原理 eNSP(Enterprise Network Simulation Platform)是一款由华为提供的.可扩展的.图形化 操作的网络仿真工具平台,主要对企业网络路由器.交换机进行软 ...

  10. docker 加入域名

    先运行docker镜像 # 进入 docker 容器 mynginx 是容器名 docker exec -i -t mynginx /bin/bash #安装vim apt-get install v ...