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);
}
}