zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接

    题目大意

      给你n个区间,然后你可以选择一个区间[l,r],我们定义S的值为区间[l,r]中包含的所有完整子区间的权值w之和减去(k imes (r-l+1)),求最大的S.

    解题思路

      这种问题有一种套路就是先固定一个端点,然后枚举另外一个端点,这个题就可以用到。我们将区间按右端点排序,然后每到一个位置i,就将从1到i的区间全部减k,这样从i开始往右数,区间减少的值正好是k,2k,3k...然后因为我们计算的区间要包含完整的子区间,我们的算法是枚举的区间右端点,所以对于一个子区间,它开始有贡献的位置是1-区间左端点的位置,我们枚举到这个区间的时候把1到区间左端点的位置全都加上区间的权值w。然后怎么判断最大的S呢?直接取最大值就行了,最大值对应的位置就是区间S的左端点。

    代码

    const int maxn = 2e5+10;
    const int maxm = 2e5+10;
    struct I {
    	ll maxx, lz;
    } tree[maxn<<2];
    int n; ll k;
    inline void push_up(int rt) {
    	tree[rt].maxx = max(tree[rt<<1].maxx, tree[rt<<1|1].maxx);
    }
    inline void push_down(int rt) {
    	if (tree[rt].lz) {
    		ll lz = tree[rt].lz;
    		I &ls = tree[rt<<1];
    		I &rs = tree[rt<<1|1];
    		ls.lz += lz, rs.lz += lz;
    		tree[rt<<1].maxx += lz, tree[rt<<1|1].maxx += lz;
    		tree[rt].lz = 0;
    	}
    }
    void update(int rt, int l, int r, int a, int b, ll val) {
    	if (l>=a && r<=b) {
    		tree[rt].lz += val;
    		tree[rt].maxx += val;
    		return;
    	}
    	push_down(rt);
    	int mid = (l+r)>>1;
    	if (a<=mid) update(rt<<1, l, mid, a, b, val);
    	if (b>mid) update(rt<<1|1, mid+1, r, a, b, val);
    	push_up(rt);
    }
    ll ask(int rt, int l, int r, int a, int b) {
    	if (l>=a && r<=b) return tree[rt].maxx;
    	push_down(rt);
    	int mid = (l+r)>>1;
    	ll maxx = 0;
    	if (a<=mid) maxx = max(maxx, ask(rt<<1, l, mid, a, b));
    	if (b>mid) maxx = max(maxx, ask(rt<<1|1, mid+1, r, a, b));
    	return maxx;
    }
    int ask2(int rt, int l, int r, ll v) {
    	if (l==r) return l;
    	push_down(rt);
    	int mid = (l+r)>>1;
    	if (tree[rt<<1].maxx == v) return ask2(rt<<1, l, mid,  v);
    	else return ask2(rt<<1|1, mid+1, r, v);
    }
    struct I2 {
    	int x, i; ll w; 
    };
    vector<I2> e[maxn];
    int main() {	
    	cin >> n >> k;
    	int x, y; ll w;
    	for (int i = 1; i<=n; ++i) {
    		scanf("%d%d%lld", &x, &y, &w);
    		e[y].push_back({x, i, w});
    	}
    	ll maxx = 0; P pos;
    	for (int i = 1; i<=200000; ++i) {
    		update(1, 1, 200000, 1, i, -k);
    		for (auto v : e[i]) {
    			update(1, 1, 200000, 1, v.x, v.w);
    			ll t = ask(1, 1, 200000, 1, v.x);
    			if (t>maxx) {
    				maxx = t;
    				pos = {ask2(1, 1, 200000, maxx), i};
    			}
    		}
    	}
    	if (!maxx) {
    		cout << 0 << endl;
    		return 0;
    	}
    	vector<int> ans;
    	for (int i = pos.x; i<=pos.y; ++i) {
    		for (auto v : e[i])
    			if (v.x>=pos.x) ans.push_back(v.i);
    	}
    	cout << maxx << ' ' << pos.x << ' ' << pos.y << ' ' << ans.size() << endl;
    	for (auto v : ans) cout << v << ' ';
    	return 0;	
    } 
    
    
  • 相关阅读:
    java pojo类
    web(一)
    java通过配置文件(Properties类)连接Oracle数据库代码示例
    java数组排序(插入排序、冒泡排序、选择排序)与递归 代码示例
    匿名内部类
    java反射机制
    ubuntu安装kvm流程
    squid代理服务问答
    ftp nfs samba比较
    Samba服务问答
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14472670.html
Copyright © 2011-2022 走看看