AT2402 [ARC072D] Dam

显然体积不变,使热量最大。

单调队列维护热量段,满足单调递增。

每次放水就取出队头。

加水就维护单调队列,融合一下。

时间复杂度 O(n)\mathcal O(n)

#include<bits/stdc++.h>

using namespace std;

#define int long long

typedef long long ll;

#define ha putchar(' ')
#define he putchar('\n')

namespace Fread
{
	const int SIZE = 1 << 15;
	char buf[SIZE], *S, *T;
	inline char getchar()
	{
		if (S == T)
		{
			T = (S = buf) + fread(buf, 1, SIZE, stdin);
			if (S == T)
				return '\n';
		}
		return *S++;
	}
}

#ifdef ONLINE_JUDGE
#define getchar Fread::getchar
#endif

inline int read()
{
	int x = 0, f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-')
			f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x * f;
}

const int _ = 5e5 + 10;

int n, L;

long double t[_], v[_];

struct Node
{
	int v; long double t;
} q[_];

signed main()
{
	n = read(), L = read();
	for(int i = 1; i <= n; ++i)
		t[i] = read(), v[i] = read();
	int l = 1, r = 0;
	int cv = 0; long double ans = 0.0000000000;
	for(int i = 1; i <= n; ++i)
	{
		while(cv + v[i] > L)
		{
			int dl = min(q[l].v, cv - (L - (int)v[i]));
			q[l].v -= dl, cv -= dl, ans -= q[l].t * dl;
			if(!q[l].v) ++l;
		}
		cv = L, ans += t[i] * v[i];
		++r, q[r].t = t[i], q[r].v = v[i];
		while(l < r && q[r - 1].t > q[r].t)
		{
			q[r - 1].t = ((q[r - 1].v * q[r - 1].t) + (q[r].v * q[r].t)) / (q[r - 1].v + q[r].v);
			q[r - 1].v += q[r].v;
			r--;
		}
		printf("%.7Lf\n", (long double)ans / L);
	}
}
posted @ 2022-12-01 09:24  蒟蒻orz  阅读(8)  评论(0)    收藏  举报  来源