题面
天上有$n$朵云,每朵云$i$会在时间$[l_i,r_i]$出现,你有$ ext C$个糖果,你可以花费$c_i$个糖果让云$i$消失,同时需要保证你最多让两朵云消失.现在有$m$个独立的询问,每次给你一个需要让阳光照$k$时间的植物,问你从时刻$0$开始,这个植物最快什么时候能长成. $n,mleq 3 imes10^5$
题解
看他的吧,这题真的麻烦。
代码
#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
", ans[i]);
return 0;
}