Codeforces 739C - Alyona and towers(线段树)

Codeforces 题目传送门 & 洛谷题目传送门

可能有人会问我为什么为这道 *2500 的 D1C 写题解,我觉得大概是想要在写题解数量上 dd ycx 吧,因为 ycx 到目前为止写了 143 篇题解,而这也是我的第 143 篇题解(((

大概和 CF1149C Tree Generator™ 比较像?做过那题这题基本可以一眼秒了(

线段树。每个区间维护以下八个值:

  • 区间第一个元素的值 \(fst\)
  • 区间最后一个元素的值 \(lst\)
  • 区间长度 \(len\)
  • 以左端点为开头的最长下降前缀的长度 \(llen\)
  • 以右端点为开头的最长上升后缀的长度 \(rlen\)
  • 以左端点为开头的先上升再下降的最长前缀长度 \(l\_tower\)
  • 以右端点为结尾的先上升再下降的最长前缀长度 \(r\_tower\)
  • 这段区间中最长的先上升后下降子序列的长度 \(mx\)

考虑合并左右两个区间:

  • \(fst\) 就直接继承左儿子的 \(fst\) 即可
  • \(lst\) 就直接继承右儿子的 \(lst\) 即可
  • \(len\) 就直接将左右儿子的 \(len\) 加起来即可
  • \(llen\) 分两种情况,如果左儿子的 \(llen\) 就等于其 \(len\),并且左儿子的 \(lst\) 大于右儿子的 \(fst\),那么该节点的 \(llen\) 等于左右节点的 \(llen\) 之和。否则该节点的 \(llen\) 等于左儿子的 \(llen\)\(rlen\) 也同理
  • \(l\_tower\) 分三种情况,如果左儿子本身就是上升序列,即左儿子的 \(rlen\) 等于其 \(len\),并且左儿子的 \(lst\) 小于右儿子的 \(fst\),那么 \(l\_tower\) 就等于左儿子的 \(rlen\) 与右儿子的 \(l\_tower\) 的和。如果左儿子的 \(l\_tower\) 等于其 \(len\),并且左儿子的 \(lst\) 大于右儿子的 \(fst\),那么 \(l\_tower\) 就等于左儿子的 \(len\) 与右儿子的 \(llen\) 之和。否则 \(l\_tower\) 等于左儿子的 \(l\_tower\)\(r\_tower\) 也同理。
  • \(mx\) 分四种情况,首先它可以从左右儿子的 \(mx\) 分别继承来,即它首先等于左右儿子 \(mx\) 的较大者。其次如果左儿子的 \(lst\) 小于右儿子的 \(fst\),那么 \(mx\) 可以用左儿子的 \(rlen\) 与右儿子的 \(l\_tower\) 之和更新;如果左儿子的 \(lst\) 大于右儿子的 \(fst\),那么 \(mx\) 可以用左儿子的 \(r\_tower\) 与右儿子的 \(llen\) 之和更新

写个结构体维护一下即可。区间修改就直接打个标记。

芜湖~做完了,记得开 long long,复杂度线对。

const int MAXN=3e5;
int n,qu,a[MAXN+5];
struct data{
	ll fst,lst;int len,llen,rlen,l_tower,r_tower,mx;
	data(){fst=lst=len=llen=rlen=l_tower=r_tower=mx=0;}
	data(int _fst,int _lst,int _len,int _llen,int _rlen,int _l_tower,int _r_tower,int _mx):
	fst(_fst),lst(_lst),len(_len),llen(_llen),rlen(_rlen),l_tower(_l_tower),r_tower(_r_tower),mx(_mx){}
	friend data operator +(data a,data b){
		data c;
		c.fst=a.fst;c.lst=b.lst;c.len=a.len+b.len;
		c.llen=(a.llen==a.len&&a.lst>b.fst)?(a.llen+b.llen):a.llen;
		c.rlen=(b.rlen==b.len&&a.lst<b.fst)?(b.rlen+a.rlen):b.rlen;
		c.l_tower=(a.rlen==a.len&&a.lst<b.fst)?(a.l_tower+b.l_tower):
				  ((a.l_tower==a.len&&a.lst>b.fst)?(a.l_tower+b.llen):(a.l_tower));
		c.r_tower=(b.llen==b.len&&a.lst>b.fst)?(b.r_tower+a.r_tower):
				  ((b.r_tower==b.len&&a.lst<b.fst)?(b.r_tower+a.rlen):(b.r_tower));
		c.mx=max(a.mx,b.mx);
		if(a.lst>b.fst) c.mx=max(c.mx,a.r_tower+b.llen);
		if(a.lst<b.fst) c.mx=max(c.mx,a.rlen+b.l_tower);
		return c;
	}
};
struct node{int l,r;ll lz;data v;} s[MAXN*4+5];
void pushup(int k){s[k].v=s[k<<1].v+s[k<<1|1].v;}
void build(int k,int l,int r){
	s[k].l=l;s[k].r=r;if(l==r){s[k].v=data(a[l],a[l],1,1,1,1,1,1);return;}
	int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}
void pushdown(int k){
	if(s[k].lz){
		s[k<<1].lz+=s[k].lz;s[k<<1].v.fst+=s[k].lz;s[k<<1].v.lst+=s[k].lz;
		s[k<<1|1].lz+=s[k].lz;s[k<<1|1].v.fst+=s[k].lz;s[k<<1|1].v.lst+=s[k].lz;
		s[k].lz=0;
	}
}
void modify(int k,int l,int r,int x){
	if(l<=s[k].l&&s[k].r<=r){
		s[k].lz+=x;s[k].v.fst+=x;s[k].v.lst+=x;
		return;
	} pushdown(k);int mid=s[k].l+s[k].r>>1;
	if(r<=mid) modify(k<<1,l,r,x);
	else if(l>mid) modify(k<<1|1,l,r,x);
	else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
	pushup(k);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,1,n);scanf("%d",&qu);
	while(qu--){
		int l,r,v;scanf("%d%d%d",&l,&r,&v);
		modify(1,l,r,v);printf("%d\n",s[1].v.mx);
	}
	return 0;
}
posted @ 2021-03-25 20:48  tzc_wk  阅读(73)  评论(0)    收藏  举报