\(\mathcal{Description}\)

  合并果子,初始果子的权值在 \(1\sim n\) 之间,权值为 \(i\) 的有 \(a_i\) 个。每次可以挑 \(x\in[L,R]\) 个果子合并成一个,代价为所挑果子权值之和。求合并所有果子的最少代价。\(T\) 组数据。

  \(T\le10\),\(n,a_i\le10^5\),\(2\le L\le R\le\sum_{i=1}^na_i\)。

\(\mathcal{Solution}\)

  把合并考虑成一棵树,树叉在 \([L,R]\) 内,可以发现总代价为每个点的深度 \(\times\) 权值之和。以此为背景证明几个结论(当然很容易直接猜到最终结论)。

  Lemma 1:最优解的非叶结点最少。否则,一定可以删除最深的非叶结点,并把它的儿子们丢给其它非叶结点,使“深度 \(\times\) 权值之和”变小。

  Lemma 2:记 \(u\) 的深度为 \(d(u)\),当树满足 Lemma 1 时,若存在非叶结点 \(d(u)<d(v)\),则 \(u\) 满叉。很显然,只要 \(v\) 存在且 \(u\) 不满,就可以把 \(v\) 的儿子接到 \(u\) 下使答案更优。由此有推论:存在最优解,其合并数量构成的序列字典序最小(先最小(\(L\)),再最大 \(R\))。

  考虑到实际问题,我们可以断言答案的合并数量为:\(\{L,L,\cdots,L,x,R,R,\cdots,R\}\) 且其中 \(R\) 尽可能多。


  不过这个题你甚至不能带堆的 \(\log\) qwq!

  由输入方式,显然一堆果子可以表示成 \((\text{权值},\text{个数})\) 二元组,初始时有 \(n\) 个二元组(有些个数是 \(0\),用于占位),它们已按权值升序排列了。考虑从队首取出若干个小果子合并成大果子,显然和出的大果子的权值是升序的,那么很多情况下大果子可以直接插在队尾。不过可能有大果子的权值属于 \([1,n]\) 的情况,我们直接把对应果子的个数 \(+1\) 即可。

  复杂度 \(\mathcal O(Tn\log\sum_{i=1}^na_i)\)。(Tiw 说的 qwq。

\(\mathcal{Code}\)

#include <queue>
#include <cstdio>
#include <iostream> typedef long long LL;
typedef std::pair<LL, LL> pll; inline char fgc () {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && ( q = buf + fread ( p = buf, 1, 1 << 17, stdin ), p == q ) ? EOF : *p ++;
} inline LL rint () {
LL x = 0; char s = fgc ();
for ( ; s < '0' || '9' < s; s = fgc () );
for ( ; '0' <= s && s <= '9'; s = fgc () ) x = x * 10 + ( s ^ '0' );
return x;
} const int MAXN = 1e5;
int n, a[MAXN + 5];
LL L, R, S, ans;
std::queue<pll> plan; struct GreadyQueue {
std::deque<pll> deq;
std::deque<pll>::iterator ptr; GreadyQueue (): ptr ( deq.end () ) {}
inline void clear () { deq.clear (), ptr = deq.end (); }
inline pll& front () { return deq.front (); }
inline void popF () {
bool eff = ptr == deq.begin ();
deq.pop_front ();
if ( eff ) ptr = deq.begin ();
}
inline void add ( const pll x ) {
ans += x.first * x.second;
for ( ; ptr != deq.end () && ptr->first < x.first; ++ ptr );
if ( ptr == deq.end () ) deq.push_back ( x ), -- ( ptr = deq.end () );
else ptr->second += x.second;
}
} Q; inline void clear () {
ans = S = 0, Q.clear ();
for ( ; !plan.empty (); plan.pop () );
} inline bool calcPlan () {
LL tR = ( S - 1 ) / ( R - 1 ) + !!( ( S - 1 ) % ( R - 1 ) ), tL = 0;
if ( tR * ( L - 1 ) > S - 1 ) return false;
LL def = tR * ( R - 1 ) - ( S - 1 );
if ( L ^ R ) {
tR -= tL = def / ( R - L ), def -= tL * ( R - L );
if ( tL ) plan.push ( pll ( L, tL ) );
if ( def ) plan.push ( pll ( R - def, 1 ) ), -- tR;
}
if ( tR ) plan.push ( pll ( R, tR ) );
return true;
} inline void followPlan () {
for ( ; !plan.empty (); plan.pop () ) {
pll stp ( plan.front () ), cur ( 0, 0 );
while ( stp.second ) {
if ( cur.second ) {
if ( cur.second + Q.front ().second >= stp.first ) {
cur.first += Q.front ().first * ( stp.first - cur.second );
Q.front ().second -= stp.first - cur.second;
Q.add ( pll ( cur.first, 1 ) ), cur = pll ( 0, 0 );
-- stp.second;
} else {
cur.first += Q.front ().second * Q.front ().first;
cur.second += Q.front ().second, Q.popF ();
continue;
}
}
LL cnt = std::min ( stp.second, Q.front ().second / stp.first );
if ( cnt ) Q.add ( pll ( Q.front ().first * stp.first, cnt ) );
stp.second -= cnt, Q.front ().second -= stp.first * cnt;
if ( stp.second ) {
cur = pll ( Q.front ().second * Q.front ().first, Q.front ().second );
Q.popF ();
}
}
}
} int main () {
freopen ( "river.in", "r", stdin );
freopen ( "river.out", "w", stdout );
for ( int T = rint (); T --; ) {
clear ();
n = rint (), L = rint (), R = rint ();
for ( int i = 1; i <= n; ++ i ) {
Q.deq.push_back ( pll ( i, a[i] = rint () ) );
S += a[i];
}
if ( !calcPlan () ) { puts ( "-1" ); continue; }
Q.ptr = Q.deq.begin (), followPlan ();
printf ( "%lld\n", ans );
}
return 0;
}

\(\mathcal{Details}\)

  用 std::deque 是因为只有它有迭代器啦 owo。

  涉及容器元素变化(特别是 poperase 之类)的时候,特别注意迭代器的操作嗷!

Solution -「LOCAL」Drainage System的更多相关文章

  1. Solution -「LOCAL」二进制的世界

    \(\mathcal{Description}\)   OurOJ.   给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...

  2. Solution -「LOCAL」大括号树

    \(\mathcal{Description}\)   OurTeam & OurOJ.   给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...

  3. Solution -「LOCAL」过河

    \(\mathcal{Description}\)   一段坐标轴 \([0,L]\),从 \(0\) 出发,每次可以 \(+a\) 或 \(-b\),但不能越出 \([0,L]\).求可达的整点数. ...

  4. Solution -「LOCAL」Burning Flowers

      灼之花好评,条条生日快乐(假装现在 8.15)! \(\mathcal{Description}\)   给定一棵以 \(1\) 为根的树,第 \(i\) 个结点有颜色 \(c_i\) 和光亮值 ...

  5. Solution -「LOCAL」画画图

    \(\mathcal{Description}\)   OurTeam.   给定一棵 \(n\) 个点的树形随机的带边权树,求所有含奇数条边的路径中位数之和.树形生成方式为随机取不连通两点连边直到全 ...

  6. Solution -「LOCAL」ZB 平衡树

    \(\mathcal{Description}\)   OurOJ.   维护一列二元组 \((a,b)\),给定初始 \(n\) 个元素,接下来 \(m\) 次操作: 在某个位置插入一个二元组: 翻 ...

  7. Solution -「LOCAL」舟游

    \(\mathcal{Description}\)   \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...

  8. Solution -「LOCAL」充电

    \(\mathcal{Description}\)   给定 \(n,m,p\),求序列 \(\{a_n\}\) 的数量,满足 \((\forall i\in[1,n])(a_i\in[1,m])\l ...

  9. Solution -「LOCAL」「cov. 牛客多校 2020 第五场 C」Easy

    \(\mathcal{Description}\)   Link.(完全一致)   给定 \(n,m,k\),对于两个长度为 \(k\) 的满足 \(\left(\sum_{i=0}^ka_i=n\r ...

随机推荐

  1. 移动Web开发实践——解决position:fixed自适应BUG

    在移动web中使用position:fixed,会踩到很多坑,在我之前的一篇文章<移动端web页面使用position:fixed问题总结>中已经总结了很多bug,但是在后续的开发中有关f ...

  2. POJ 2456 Aggressive cows(贪心 + 二分)

    原题链接:Aggressive cows 题目大意:农夫 建造了一座很长的畜栏,它包括  个隔间,这些小隔间依次编号为. 但是, 的  头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争 ...

  3. 51 Nod 1133 不重叠的线段 (贪心算法)

    原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1133 题目分析:感觉这到第不应该被分到二级算法题,比 109 ...

  4. 解决excel两表之间数据关联关系,知道这几招就够了

    用过SAP的凭证批量录入模板(Excel文件)的都知道,一个凭证由[抬头]和多个[行项目]组成,这是一个关于excel两表信息关联的典型场景. 这里头蕴藏着一个麻烦:当我们需要一次性录入多个凭证时,如 ...

  5. 超详细的编码实战,让你的springboot应用识别图片中的行人、汽车、狗子、喵星人(JavaCV+YOLO4)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. 园子的推广博文:欢迎收看 Apache Flink 技术峰会 FFA 2021 的视频回放

    园子专属收看链接:https://developer.aliyun.com/special/ffa2021/live#?utm_content=g_1000316459 Flink Forward 是 ...

  7. 《剑指offer》面试题66. 构建乘积数组

    问题描述 给定一个数组 A[0,1,-,n-1],请构建一个数组 B[0,1,-,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×-×A[i-1]×A[i+1]×-×A[n-1].不能使用 ...

  8. rocketmq实现延迟队列精确到秒级实现方案2-时间轮和delay-file实现

    上图是通过RocketMQ源码分析一个实现原理方案示意图. 分为两个部分: 消息的写入消息的Schedule 在写入CommitLog之前,如果是延迟消息,按照每10分钟写入delayfile文件,对 ...

  9. nRF24L01基于FIFO TX队列的发送性能优化

    RF24项目代码分析 头文件 https://github.com/nRF24/RF24/blob/master/RF24.h 源文件 https://github.com/nRF24/RF24/bl ...

  10. 解决vscode下载很慢的问题

    1.打开vscode官网,https://code.visualstudio.com; 2.点击下载稳定版;这里我的电脑是win10版本 3.下载时可以去谷歌的下载内容里面,看到正在下载的vscode ...