[CEOI2018]Global warming

[CEOI2018]Global warming

题目大意:

给定\(n(n\le2\times10^5)\),你可以将任意\(a_{l\sim r}(1\le l\le r\le n)\)每一个元素加上一个\(d(|d|\le x)\),求\(a\)的LIS长度。

思路:

不难发现区间加一个数是为了使得LIS中间一段比左边一段大,而右边一段本来就比中间的大,那么我们给右边一段同时加上也不会影响答案。因此我们可以给一个后缀加上\(x\)求LIS即可。

用两个树状数组分别维护,当前是否是已被增加过的后缀,前缀LIS的最大值。

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

源代码:

#include<cstdio>
#include<cctype>
#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;
}
const int N=2e5+1;
int a[N],tmp[N*2];
class SegmentTree {
	private:
		int val[N*2];
		int lowbit(const int &x) const {
			return x&-x;
		}
	public:
		void modify(int p,const int &x) {
			for(;p<=tmp[0];p+=lowbit(p)) {
				val[p]=std::max(val[p],x);
			}
		}
		int query(int p) const {
			int ret=0;
			for(;p;p-=lowbit(p)) {
				ret=std::max(ret,val[p]);
			}
			return ret;
		}
};
SegmentTree t[2];
int main() {
	const int n=getint(),x=getint();
	for(register int i=1;i<=n;i++) {
		tmp[i]=a[i]=getint();
		tmp[n+i]=a[i]+x;
	}
	std::sort(&tmp[1],&tmp[n*2]+1);
	tmp[0]=std::unique(&tmp[1],&tmp[n*2]+1)-&tmp[1];
	for(register int i=1;i<=n;i++) {
		const int pos1=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,a[i]+x)-tmp;
		t[1].modify(pos1,t[0].query(pos1-1)+1);
		t[1].modify(pos1,t[1].query(pos1-1)+1);
		const int pos0=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,a[i])-tmp;
		t[0].modify(pos0,t[0].query(pos0-1)+1);
	}
	printf("%d\n",t[1].query(tmp[0]));
	return 0;
}
posted @ 2018-09-12 11:11  skylee03  阅读(443)  评论(0编辑  收藏  举报