• 【CF833E】Caramel Clouds


    【CF833E】Caramel Clouds

    题面

    洛谷

    题目大意:

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

    (n,mleq 3e5)

    题解

    这题好神仙啊。。。

    我们首先记几个东西:

    (Free:)表示当前空着的长度和

    (single[x]:)表示只有(x)覆盖的长度

    (opt[x]:)选出的两朵云中必定包含(x)的最大长度

    (Top:)(opt)的最大值

    (cross[x][y]:)表示只有(x,y)覆盖的长度

    然后用一个(set)维护当前还未消失的云

    分类讨论一下(set)中云的个数:

    1、当(set)中没有云时,直接让(Free)加上贡献即可

    2、当(set)中只有一朵云,更新(single)以及(opt)

    3、当(set)中有两朵云,更新(cross)(opt)

    4、当(set)中云朵数大于二,不用管,因为此时一定不会比云朵数小于等于二的时候答案更优

    至于更新的方法,看代码应该能看懂

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    #include <set>
    #include <map> 
    using namespace std; 
    inline int gi() { 
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    }
    void chkmax(int &x, int y) { if (x < y) x = y; } 
    const int MAX_N = 3e5 + 5;
    struct Cloud { int l, r, c; } cld[MAX_N];
    bool operator < (const Cloud &l, const Cloud &r) { return l.c < r.c; }
    struct Query { int id, t; } q[MAX_N];
    bool operator < (const Query &l, const Query &r) { return l.t < r.t; }
    struct Node { int t, op, id; } a[MAX_N << 1]; int tot = 0; 
    bool operator < (const Node &l, const Node &r) { return l.t < r.t; } 
    int N, M, C, single[MAX_N], opt[MAX_N], ans[MAX_N];
    map<int, int> cross[MAX_N];
    set<int> s;
    set<int>::iterator ite;
    int Free, Top; 
    #define lson (o << 1)
    #define rson (o << 1 | 1)
    int mx[MAX_N << 2];
    void modify(int o, int l, int r, int pos, int v) {
    	if (l == r) return (void)(mx[o] = v);
    	int mid = (l + r) >> 1;
        if (pos <= mid) modify(lson, l, mid, pos, v);
    	else modify(rson, mid + 1, r, pos, v);
    	mx[o] = max(mx[lson], mx[rson]); 
    }
    int find(int o, int l, int r) {
    	if (l == r) return l; 
    	int mid = (l + r) >> 1;
    	if (mx[lson] > mx[rson]) return find(lson, l, mid);
    	else return find(rson, mid + 1, r); 
    }
    int query(int o, int l, int r, int ql, int qr) {
    	if (ql <= l && r <= qr) return find(o, l, r); 
    	int mid = (l + r) >> 1, res = 0; 
    	if (ql <= mid) res = query(lson, l, mid, ql, qr); 
    	if (qr > mid) {
    		int tmp = query(rson, mid + 1, r, ql, qr); 
    		if (single[tmp] > single[res]) res = tmp; 
    	}
    	return res; 
    }
    int sum(int x, int y) {
    	if (x > y) swap(x, y); 
    	return single[x] + single[y] + cross[x][y]; 
    } 
    void solve() {
    	int now = 0, pos = 1; 
    	for (int i = 1; i <= tot; i++) {
    		int dlt = a[i].t - now; now = a[i].t;
    		if (!s.size()) Free += dlt; 
    		else if (s.size() == 1) {
    		    ite = s.upper_bound(0); int x = *ite;
    			single[x] += dlt; modify(1, 1, N, x, single[x]);
    			opt[x] += dlt; 
    			int rem = C - cld[x].c; 
    			if (rem >= 0) {
    				int val = single[x]; 
    				if (rem >= cld[1].c) {
    					int l = 1, r = N, res = 1; 
    					while (l <= r) {
    						int mid = (l + r) >> 1; 
    						if (cld[mid].c <= rem) 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(1, 1, N, ql, qr))); ql = 1, qr = x - 1; }
    					if (ql <= qr) chkmax(val, sum(x, query(1, 1, N, ql, qr))); 
    				}
    				chkmax(opt[x], val);
    				chkmax(Top, opt[x]); 
    			} 
    		} else if (s.size() == 2) {
    			ite = s.upper_bound(0); int x = *ite;
    			++ite; int y = *ite;
    			if (cross[x].count(y) > 0) cross[x][y] += dlt;
    			else cross[x][y] = dlt; 
    			if (cld[x].c + cld[y].c <= C) { 
    				chkmax(opt[x], sum(x, y)); chkmax(opt[y], sum(x, y));
    				chkmax(Top, opt[x]); 
    			} 
    		}
    		while (pos <= M && Top + Free >= q[pos].t) ans[q[pos].id] = now - (Top + Free - q[pos].t), ++pos;
    		if (pos > M) break;
    		if (a[i].op == 1) s.insert(a[i].id);
    		else s.erase(a[i].id); 
    	} 
    } 
    int main () {
    	N = gi(), C = gi(); 
    	for (int i = 1; i <= N; i++) cld[i].l = gi(), cld[i].r = gi(), cld[i].c = gi(); 
    	sort(&cld[1], &cld[N + 1]);
    	for (int i = 1; i <= N; i++) {
    		a[++tot] = (Node){cld[i].l, 1, i};
    		a[++tot] = (Node){cld[i].r, -1, i}; 
    	}
    	sort(&a[1], &a[tot + 1]);
    	a[++tot] = (Node){(int)(2e9 + 7), 1, N + 1}; 
    	M = gi(); 
    	for (int i = 1; i <= M; i++) q[i].id = i, q[i].t = gi();
    	sort(&q[1], &q[M + 1]);
    	solve(); 
    	for (int i = 1; i <= M; i++) printf("%d
    ", ans[i]); 
    	return 0;  
    } 
    
    
  • 相关阅读:
    hbuilder外置服务器设置(局域网移动端调试)
    【转载】解决微信OAuth2.0网页授权回调域名只能设置一个的问题
    【转载】如何使用PHP构建一个高性能的弹幕后端服务
    【转载】PHP学习资源整理
    【php基础】php运算符 php取整函数
    Browser 对象(一、history)
    Opencv 图像平滑基础二维离散卷积C++ API
    Opencv 图像平滑基础二维离散卷积 python API
    道格拉斯轨迹抽稀算法Android 百度地图SDK
    Opencv 几何变换
  • 原文地址:https://www.cnblogs.com/heyujun/p/10207742.html
Copyright © 2020-2023  润新知