• CF833E Caramel Clouds


    题面

    天上有$n$朵云,每朵云$i$会在时间$[l_i,r_i]$出现,你有$ ext C$个糖果,你可以花费$c_i$个糖果让云$i$消失,同时需要保证你最多让两朵云消失.现在有$m$个独立的询问,每次给你一个需要让阳光照$k$时间的植物,问你从时刻$0$开始,这个植物最快什么时候能长成. $n,mleq 3 imes10^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
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    MFC中,什么是CALLBACK函数,什么是WINAPI函数,二者有什么区别和联系?
    浙江移动话费计算-js代码
    [转]C#网页自动登录和提交POST信息的多种方法
    JavaScript小数四舍五入toFixed
    C#.NET应用程序实现网页自动登录
    VC改变对话框按钮字体颜色和背景的解决方案(转)
    WPF窗口阴影
    用MVVM模式开发中遇到的零散问题总结(1)
    NPOI之Excel——合并单元格、设置样式、输入公式
    近距离接触RAC DRM
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10209438.html
Copyright © 2020-2023  润新知