CodeForces 1299C Water Balance

首先,$\mathcal O(n^2)$ 的思路十分好想。

大概就是说,我们发现答案序列是单调不降的,所以倒着来,对于每个位置 $i$,我们找一个它后面的位置 $j$,使得 $\frac{\sum_{k=i}^{j} a_k}{j-i+1}$ 是最小的,然后把这一段全部赋值为这个值。这样,我们就在优先确保前面的值更优时,得到了一个可靠的贪心策略。

因为 $10^6$ 肯定要更好的方法,所以考虑优化。当处理位置 $i$ 的时候,$(i, n]$ 已经处理好了,成为了一个不降的,若干个连续段组成的数列。而对于连续的一段,我们 要不一起选,要不一起不选,所以就可以用一个栈来维护后面的这个东西。栈里存一个三元组,表示这一段的左端点 $l$,右端点 $r$,以及总和 $w$。

比如这时,已选的数字的总和为 $sum$,已选的数字总个数为 $tot$,显然,如果处于栈顶的那一段(不妨叫做 $top$)能够 拖低平均值,即 $\frac{w_{top}}{r_{top}-l_{top} +1} \le \frac{sum}{tot}$(注意等于也可以不加,反正不会改变什么),那么我们就要选这一段。细节问题是避免浮点计算,交叉相乘,看看 $w_{top} \times tot \le sum \times (r_{top}-l_{top}+1)$ 就行了。

时间复杂度 $\mathcal O(n)$,下面是代码。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, l[N], r[N], top, a[N];
long long w[N];
double ans[N];
int main()
{
	scanf("%d", &n);
	for(register int i = 1; i <= n; i++) scanf("%d", &a[i]);
	top = 1;
	l[1] = r[1] = n;
	w[1] = a[n];
	l[0] = n + 1;
	for(register int i = n - 1; i; i--)
	{
		int tot = 1;
		long long sum = a[i];
		while(top && w[top] * tot <= sum * (r[top] - l[top] + 1))
		{
			sum += w[top];
			tot += r[top] - l[top] + 1;
			top--;
		}
		top++;
		r[top] = l[top - 1] - 1;
		l[top] = i;
		w[top] = sum;
	}
	for(register int i = 1; i <= top; i++)
		for(register int j = l[i]; j <= r[i]; j++) ans[j] = 1.0 * w[i] / (r[i] - l[i] + 1);
	for(register int i = 1; i <= n; i++) printf("%.10lf\n", ans[i]);
	return 0;
}

吐槽:

  • 为啥 $\mathcal O(n^2)$ 能水过去?QwQ
  • 为啥全部开 $\texttt{long double}$ 会 TLE? QwQ
  • 为啥用 $\texttt{iostream}$ 会卡常?QwQ

所以这是一道毒瘤题……

原文地址:https://www.cnblogs.com/syksykCCC/p/CF1299C.html

时间: 2024-07-31 05:35:20

CodeForces 1299C Water Balance的相关文章

Codeforces 343D Water Tree(DFS序+线段树+技巧)

题目链接:http://codeforces.com/problemset/problem/343/D 题目: Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water. The vertices of the tree are numbered f

CodeForces 343D water tree(树链剖分)

Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water. The vertices of the tree are numbered from 1 to n with the root at vertex 1. For each vertex, t

codeforces 343D Water Tree 树链剖分 dfs序 线段树 set

题目链接 这道题主要是要考虑到同一棵子树中dfs序是连续的 然后我就直接上树剖了... 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=600005; 4 5 struct Node 6 { 7 int l,r; 8 int value; 9 void init() 10 { 11 l=r=value=0; 12 } 13 }tree[4*MAXN]; 14 vector<int>nei[MAXN]

Codeforces 343D Water Tree & 树链剖分教程

原题链接 题目大意 给定一棵根为1,初始时所有节点值为0的树,进行以下三个操作: 将以某点为根的子树节点值都变为1 将某个节点及其祖先的值都变为0 *询问某个节点的值 解题思路 这是一道裸的树链剖分题.下面详细地介绍一下树链剖分. 树链剖分预备知识: 线段树.DFS序 树链剖分想法|起源 首先,如果一棵树退化成一条链,那么它会有非常好的性质.我们可以用线段树等数据结构来维护相关操作,使得效率更高.那么我们考虑一般的树,它是否能被分成一些链,使它们也能更高效地进行某些操作? 算法流程 以下以点带权

Codeforces 343D Water Tree

题意简述 维护一棵树,支持以下操作: 0 v:将以v为跟的子树赋值为1 1 v:将v到根节点的路径赋值为0 2 v:询问v的值 题解思路 树剖+珂朵莉树 代码 #include <set> #include <cstdio> #define IT std::set<Node>::iterator const int N=500005; int n,q,u,v,opt,x,cnt; int h[N],to[N<<1],nxt[N<<1]; int

[Codeforces 1242C]Sum Balance

Description 题库链接 给你 \(k\) 个盒子,第 \(i\) 个盒子中有 \(n_i\) 个数,第 \(j\) 个数为 \(x_{i,j}\).现在让你进行 \(k\) 次操作,第 \(i\) 次操作要求从第 \(i\) 个盒子中取出一个元素(这个元素最开始就在该盒子中),放入任意一个你指定的盒子中,要求经过 \(k\) 次操作后 所有盒子元素个数和最开始相同: 所有盒子元素总和相等 询问是否存在一种操作方式使之满足,若存在,输出任意一种方案即可. \(1\leq k\leq 15

CF1300E Water Balance

题目链接 problem 给出一个长度为n的序列,每次可以选择一个区间\([l,r]\)并将区间\([l,r]\)内的数字全部变为这些数字的平均数.该操作可以进行任意多次. 求出进行任意次操作后可以得到的字典序最小的序列. solution 可以证明不存在一个数字被进行两次或以上运算.即不存在如下情况: 显然\([2,3]\)处的平均值小于\([1,2]\)处的平均值(否则红色线不会包含2,3).4处的值大于\([1,3]\)的平均值(否则红色线会包含4).然后蓝色线进行选择的时候,因为\([1

使用async解决nodejs异步问题

项目要求:1.对用户的煤.水.电的使用金额对用户进行每周短信提醒. 2.当爬虫爬来的煤.水.电的剩余金额小于10元时,对用户进行短信提醒. 数据库描诉:mongodb  建了4张表    分别分 每周提醒表.水费表.电费表.煤气表 每周提醒表:用户名.用户id.是否开/关提醒功能.用户是否关联煤.水.电.用户电话 电费表:用户名.用户id.社区编号.供电公司编号.是否开/关提醒.剩余电费.用户电话.更新时间.上次更新时间.上次更新剩余电费. 遇到问题描诉:使用nodejs开发,实现每周六晚上短信

codeforces 17C Balance

codeforces 17C Balance 题意 题解 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(a) (int)a.size() #define de(a) co