CF833E Caramel Clouds

题面

天上有$n$朵云,每朵云$i$会在时间$[l_i,r_i]$出现,你有$\text C$个糖果,你可以花费$c_i$个糖果让云$i$消失,同时需要保证你最多让两朵云消失.现在有$m$个独立的询问,每次给你一个需要让阳光照$k$时间的植物,问你从时刻$0$开始,这个植物最快什么时候能长成. $n,m\leq 3\times10^5$

题解

神仙$blog$

看他的吧,这题真的麻烦。

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<map>
#include<set>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while(ch != '-' && (!isdigit(ch))) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

template<typename T> inline void Chkmax(T &a, const T &b) { if(a < b) a = b; }
const int maxn(3e5 + 10);
#define LESS(a, b) inline bool operator < (const a &lhs, const a &rhs)\
	{ return lhs.b < rhs.b; }
struct cloud { int l, r, c; } cl[maxn];
struct Query { int id, t; } q[maxn];
struct node { int t, opt, id; } a[maxn << 1]; int cnt_node;
LESS(cloud, c) LESS(Query, t) LESS(node, t);

using std::map; using std::set;
int n, m, C, Len[maxn], Inc[maxn], ans[maxn];
map<int, int> cover[maxn];
set<int> s; set<int>::iterator It;
int Empty, Max, max[maxn << 2];

#define son(i) ((root << 1) | i)
void update(int id, int v, int root = 1, int l = 1, int r = n)
{
	if(l == r) return (void) (max[root] = v);
	int mid = (l + r) >> 1;
	if(id <= mid) update(id, v, son(0), l, mid);
	else update(id, v, son(1), mid + 1, r);
	max[root] = std::max(max[son(0)], max[son(1)]);
}

int findMax(int root, int l, int r)
{
	if(l == r) return l;
	int mid = (l + r) >> 1;
	if(max[son(0)] > max[son(1)]) return findMax(son(0), l, mid);
	else return findMax(son(1), mid + 1, r);
}

int query(int ql, int qr, int root = 1, int l = 1, int r = n)
{
	if(ql <= l && r <= qr) return findMax(root, l, r);
	int mid = (l + r) >> 1, ans = 0;
	if(ql <= mid) ans = query(ql, qr, son(0), l, mid);
	if(qr > mid)
	{
		int res = query(ql, qr, son(1), mid + 1, r);
		if(Len[res] > Len[ans]) ans = res;
	}
	return ans;
}

inline int sum(int x, int y)
{
	if(x > y) std::swap(x, y);
	return Len[x] + Len[y] + cover[x][y];
}

void calc()
{
	int now = 0, pos = 1;
	for(RG int i = 1; i <= cnt_node; i++)
	{
		int delta = a[i].t - now; now = a[i].t;
		if(s.size() == 0) Empty += delta;
		else if(s.size() == 1)
		{
			int x = *s.begin();
			Len[x] += delta; update(x, Len[x]);
			Inc[x] += delta; int cost = C - cl[x].c;
			if(cost >= 0)
			{
				int val = Len[x];
				if(cost >= cl[1].c)
				{
					int l = 1, r = n, res = 1;
					while(l <= r)
					{
						int mid = (l + r) >> 1;
						if(cl[mid].c <= cost) res = mid, l = mid + 1;
						else r = mid - 1;
					}

					int ql = 1, qr = res;
					if(x == qr) --qr;
					if(x < qr)
					{
						ql = x + 1;
						if(ql <= qr) Chkmax(val, sum(x, query(ql, qr)));
						ql = 1, qr = x - 1;
					}

					if(ql <= qr) Chkmax(val, sum(x, query(ql, qr)));
				}

				Chkmax(Inc[x], val), Chkmax(Max, Inc[x]);
			}
		}
		else if(s.size() == 2)
		{
			It = s.begin(); int x = *It;
			++It; int y = *It; cover[x][y] += delta;
			if(cl[x].c + cl[y].c <= C)
			{
				Chkmax(Inc[x], sum(x, y)), Chkmax(Inc[y], sum(x, y));
				Chkmax(Max, Inc[x]);
			}
		}
		while(pos <= m && Max + Empty >= q[pos].t)
			ans[q[pos].id] = now - (Max + Empty - q[pos].t), ++pos;
		if(pos > m) break;
		if(a[i].opt == 1) s.insert(a[i].id); else s.erase(a[i].id);
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	file(cpp);
#endif
	using std::sort;
	n = read(), C = read();
	for(RG int i = 1; i <= n; i++) cl[i] = (cloud) {read(), read(), read()};
	sort(cl + 1, cl + n + 1);
	for(RG int i = 1; i <= n; i++)
		a[++cnt_node] = (node) {cl[i].l, +1, i},
		a[++cnt_node] = (node) {cl[i].r, -1, i};
	sort(a + 1, a + cnt_node + 1);
	a[++cnt_node] = (node) {(int)(2e9 + 7), 1, n + 1};
	m = read();
	for(RG int i = 1; i <= m; i++) q[i] = (Query) {i, read()};
	sort(q + 1, q + m + 1); calc();
	for(RG int i = 1; i <= m; i++) printf("%d\n", ans[i]);
	return 0;
}
posted @ 2019-01-02 16:47  xgzc  阅读(408)  评论(0编辑  收藏  举报