Loading

CodeForces-739C Alyona and towers 线段树经典套路之维护左中右

CodeForces-739C Alyona and towers 线段树经典套路之维护左中右

题意

现在有\(n\)个数,\(m\)个操作,每次区间加一个数,对于每一次操作,找出最长的\(a_l...a_r\),满足存在\(k\)\([l,r]\)

\[a_l < a_{l+1}<a_{l+2} < ...<a_k > a_{k+1} > a_{k+2}>...>a_r \]

\[1\leq n \leq 3\cdot10^5\\ 1\leq a_i \leq10^9\\ 1\leq m \leq 3\cdot 10^5\\ 1 \leq d_i \leq 10^9 \]

分析

线段树的维护左中右套路,具体此题,只需维护好以下变量来方便我们PUSH_UP

左端点开始的最长上升长度\(ul\),左端点开始的最长下降序列长度\(dl\)

左端点开始的山峰长度\(udl\)

右端点结束的最长上升长度\(ur\),右端点结束的最长下降长度\(dr\)

右端点结束的山峰长度\(udr\)

区间山峰最大值\(ans\)

懒标记\(tag\)

区间左端点的值\(l\),右端点的值\(r\)

PUSH理清楚就好了

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define pii pair<double,double>

using namespace std;
typedef long long ll;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9'){
		if(ch == '-')  f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x =x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
} 

struct SegmentTree{
	struct Node{
		int ul,dl,ur,dr,udl,udr,ans;
		ll lazy,l,r;
	};
	vector<Node> node;
	int n;
	SegmentTree(int n):n(n),node((n + 1) << 2){}
	
	void push_up(int i,int l,int mid,int r){
		node[i].l = node[i << 1].l,node[i].r = node[i << 1|1].r;
		node[i].ans = max(node[i << 1].ans,node[i << 1|1].ans);
		
		int llen = mid - l + 1,rlen = r - mid;
		node[i].ul = node[i << 1].ul,node[i].dl = node[i << 1].dl;
		node[i].ur  = node[i << 1|1].ur,node[i].dr = node[i << 1|1].dr;
		node[i].udl = node[i << 1].udl,node[i].udr = node[i << 1|1].udr;
		
		if(node[i << 1].r < node[i << 1|1].l) {
			if(node[i << 1].ul == llen) node[i].ul += node[i << 1|1].ul;
			if(node[i << 1|1].ur == rlen) node[i].ur += node[i << 1].ur;
			if(node[i << 1|1].udr == rlen) node[i].udr += node[i << 1].ur;
			if(node[i << 1].ul == llen) node[i].udl = max(node[i].udl,llen + node[i << 1|1].udl);
			node[i].ans = max(node[i].ans,node[i << 1|1].udl + node[i << 1].ur); 
			}	
		else if(node[i << 1].r > node[i << 1|1].l) {
			if(node[i << 1].dl == llen) node[i].dl += node[i << 1|1].dl;
			if(node[i << 1|1].dr == rlen) node[i].dr += node[i << 1].dr;
			if(node[i << 1].udl == llen) node[i].udl += node[i << 1|1].dl;
			if(node[i << 1|1].dr == rlen) node[i].udr = max(node[i].udr,rlen + node[i << 1].udr);
			node[i].ans = max(node[i].ans,node[i << 1].udr + node[i << 1|1].dl);
		}
	}
	
	void update(int i,ll tag){
		node[i].l += tag;
		node[i].r += tag;
		node[i].lazy += tag;
	}
	
	void push(int i){
		if(node[i].lazy){
			update(i << 1,node[i].lazy);
			update(i << 1|1,node[i].lazy);
			node[i].lazy = 0;
		}
	}
	
	void build(int i,int l,int r){
		if(l == r) {
			node[i].l = node[i].r = rd();
			node[i].ul = node[i].ur = node[i].dl = node[i].dr = node[i].udr = node[i].udl = 1;
			node[i].ans = 1;
			node[i].lazy = 0;
			return;
		}
		int mid = l + r >> 1;
		build(i << 1,l,mid);
		build(i << 1|1,mid + 1,r);
		push_up(i,l,mid,r);
	} 
	
	void update(int i,int l,int r,int L,int R,ll v){
		if(L <= l && r <= R) {
			node[i].l += v;
			node[i].r += v;
			node[i].lazy += v;
			return;
		}
		int mid = l + r >> 1;
		push(i);
		if(L <= mid) update(i << 1,l,mid,L,R,v);
		if(mid + 1 <= R) update(i << 1|1,mid + 1,r,L,R,v);
		push_up(i,l,mid,r);
	}
};
	
int main(){
	int n = rd();
	SegmentTree seg(n);	
	seg.build(1,1,n);
	int q = rd();
	while(q--){
		int l = rd();
		int r = rd();
		int v = rd();
		seg.update(1,1,n,l,r,v);
		printf("%d\n",seg.node[1].ans);
	}
}

posted @ 2021-03-04 10:39  MQFLLY  阅读(70)  评论(0编辑  收藏  举报