[CF115E]Linear Kingdom Races

[CF115E]Linear Kingdom Races

题目大意:

\(n(n\le10^5)\)个物品,编号为\(1\sim n\)。选取第\(i\)个物品需要\(c_i\)的代价。另外有\(m(m\le10^5)\)个条件,表示若\(l_i\sim r_i\)间的物品全部选择,可以获得\(p_i\)的收益。求最大收益。

思路:

\(f[i]\)表示考虑完前\(i\)个物品是否选取能获得的最大收益。

转移方程为\(f[i]=\max\{f[j]-\texttt{cost}(j+1,i)+\texttt{profit}(j+1,i)\}\)

使用线段树优化即可。

时间复杂度\(\mathcal O((n+m)\log n)\)

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
const int N=2e5+1,M=2e5;
int c[N];
int64 f[N];
struct Segment {
	int l,r,p;
	bool operator < (const Segment &rhs) const {
		return r<rhs.r;
	}
};
Segment s[M];
class SegmentTree {
	#define _left <<1
	#define _right <<1|1
	#define mid ((b+e)>>1)
	private:
		int64 val[N<<2],tag[N<<2];
		void push_up(const int &p) {
			val[p]=std::max(val[p _left],val[p _right]);
		}
		void push_down(const int &p) {
			if(tag[p]==0) return;
			tag[p _left]+=tag[p];
			tag[p _right]+=tag[p];
			val[p _left]+=tag[p];
			val[p _right]+=tag[p];
			tag[p]=0;
		}
	public:
		void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int64 &x) {
			if(b==l&&e==r) {
				val[p]+=x;
				tag[p]+=x;
				return;
			}
			push_down(p);
			if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x);
			if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x);
			push_up(p);
		}
		int64 query(const int &p,const int &b,const int &e,const int &l,const int &r) {
			if(b==l&&e==r) return val[p];
			push_down(p);
			int64 ret=0;
			if(l<=mid) ret=std::max(ret,query(p _left,b,mid,l,std::min(mid,r)));
			if(r>mid) ret=std::max(ret,query(p _right,mid+1,e,std::max(mid+1,l),r));
			return ret;
		}
	#undef _left
	#undef _right
	#undef mid
};
SegmentTree t;
int main() {
	const int n=getint(),m=getint();
	for(register int i=1;i<=n;i++) c[i]=getint();
	for(register int i=0;i<m;i++) {
		const int l=getint(),r=getint(),p=getint();
		s[i]=(Segment){l,r,p};
	}
	std::sort(&s[0],&s[m]);
	for(register int i=1,j=0;i<=n;i++) {
		t.modify(1,0,n,0,i-1,-c[i]);
		for(;j<m&&s[j].r<=i;j++) {
			t.modify(1,0,n,0,s[j].l-1,s[j].p);
		}
		f[i]=std::max(f[i-1],t.query(1,0,n,0,i-1));
		t.modify(1,0,n,i,i,f[i]);
	}
	printf("%lld\n",f[n]);
	return 0;
}
posted @ 2018-07-27 23:13  skylee03  阅读(186)  评论(0)    收藏  举报