CF923B Producing Snow

听说赛前写题解可以 rp++。

我们需要求每天融化总数,但直接求并不容易,考虑求每一堆的起始时间到结束时间,那么这一区间内每一天都应该贡献 +1+1注意每个区间的最后一天可能融化不满

考虑对于每个数二分加前缀和找到终止天数,然后使用线段树区间 +1+1,特判最后一个数即可,时间复杂度 O(nlogn)O(n \log n)

注意贡献 +1+1 指这一天的融化和 +ti+t_i

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

#define int long long

const int N = 1e5 + 5;

int n, a[N], b[N], c[N], s[N], f[N], ext[N];

class SegmentTree
{
public:
	struct Node
	{
		int l, r, sum, add;
	}tr[N << 2];
	void pushup(int u)
	{
		tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
	}
	void pushdown(int u)
	{
		Node& rt = tr[u], & lf = tr[u << 1], & rit = tr[u << 1 | 1];
		if (rt.add)
		{
			lf.add += rt.add;
			lf.sum += (lf.r - lf.l + 1) * rt.add;
			rit.add += rt.add;
			rit.sum += (rit.r - rit.l + 1) * rt.add;
			rt.add = 0;
		}
	}
	void build(int u, int l, int r)
	{
		tr[u] = { l, r, 0, 0 };
		if (l == r) return;
		int mid = l + r >> 1;
		build(u << 1, l, mid);
		build(u << 1 | 1, mid + 1, r);
	}
	void update(int u, int l, int r, int p)
	{
		if (tr[u].l >= l and tr[u].r <= r)
		{
			tr[u].add += p;
			tr[u].sum += (tr[u].r - tr[u].l + 1) * p;
			return;
		}
		pushdown(u);
		int mid = tr[u].l + tr[u].r >> 1;
		if (l <= mid) update(u << 1, l, r, p);
		if (r > mid) update(u << 1 | 1, l, r, p);
		pushup(u);
	}
	int query(int u, int x)
	{
		if (tr[u].l == tr[u].r) return tr[u].sum;
		pushdown(u);
		int mid = tr[u].l + tr[u].r >> 1;
		if (x <= mid) return query(u << 1, x);
		return query(u << 1 | 1, x);
	}
}t;

signed main()
{
	scanf("%lld", &n);
	t.build(1, 1, n);
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for (int i = 1; i <= n; i++)
	{
		scanf("%lld", &b[i]);
		s[i] = s[i - 1] + b[i];
	}
	for (int i = 1; i <= n; i++)
	{
		c[i] = i;
		if (a[i] <= b[i])
		{
			ext[i] += a[i];
			continue;
		}
		int l = i, r = n + 1;
		while (l + 1 < r)
		{
			int mid = l + r >> 1;
			if (s[mid] - s[i - 1] >= a[i]) r = mid;
			else l = mid;
		}
		c[i] = min(r, n);
		t.update(1, i, c[i], 1);
		if (s[r] - s[i - 1] >= a[i])
		{
			f[r] += b[r] - (a[i] - (s[r - 1] - s[i - 1]));
		}
	}
	for (int i = 1; i <= n; i++)
	{
		printf("%lld ", b[i] * t.query(1, i) - f[i] + ext[i]);
	}
	printf("\n");
	return 0;
}
posted @   HappyBobb  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示