UESTC 1425 Another LCIS

本文从WordPress迁移而来, 查看全部WordPress迁移文章

线段树

1Y了这题。线段树记录几个信息,区间最左端和最右端的元素first,last

前缀和后缀最长长度,pl,sl

区间最长长度Max

修改操作后的增量delta

对于查询的一个区间

now.Max = {左.Max,右.Max,左.sl+右.pl},即分治的思想,横跨两边

PushDown和PushUp都有讲究

Del只是写出去不让updata过于庞大

Do其实作用和PushUp作用可以说一样的,写得有些累赘了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 100010
#define lson(i) ((i)<<1)
#define rson(i) ((i)<<1|1)

struct SegTree{
int l,r,mid,len;
int Max;
int first,pl;
int last,sl;
int lazy,delta;
SegTree(){}
SegTree(int __l,int __r){
l = __l; r = __r; mid = (l+r)>>1; len = r-l+1;
Max = 0; first = last = 0; pl = sl = 0; lazy = delta = 0;
}
}t[N<<2];

void PushUp(int rt){
t[rt].first = t[lson(rt)].first;
t[rt].last = t[rson(rt)].last;
t[rt].pl = t[lson(rt)].pl;
t[rt].sl = t[rson(rt)].sl;
if(t[lson(rt)].pl == t[lson(rt)].len && t[lson(rt)].last < t[rson(rt)].first){
t[rt].pl = t[lson(rt)].pl + t[rson(rt)].pl;
}
if(t[rson(rt)].sl == t[rson(rt)].len && t[lson(rt)].last < t[rson(rt)].first){
t[rt].sl = t[lson(rt)].sl + t[rson(rt)].sl;
}
t[rt].Max = max(t[lson(rt)].Max,t[rson(rt)].Max);
if(t[lson(rt)].last < t[rson(rt)].first){
t[rt].Max = max(t[rt].Max,t[lson(rt)].sl+t[rson(rt)].pl);
}
}

void build(int rt,int a,int b){
t[rt] = SegTree(a,b);
if(a == b){
int x;
scanf("%d",&x);
t[rt].first = t[rt].last = x;
t[rt].pl = t[rt].sl = t[rt].Max = 1;
return ;
}
int mid = t[rt].mid;
build(lson(rt),a,mid);
build(rson(rt),mid+1,b);
PushUp(rt);
}

void Del(int rt,int val){
t[rt].first += val;
t[rt].last += val;
t[rt].delta += val;
t[rt].lazy = 1;
}

void PushDown(int rt){
if(t[rt].lazy == 0) return ;
Del(lson(rt),t[rt].delta);
Del(rson(rt),t[rt].delta);
t[rt].delta = t[rt].lazy = 0;
}

void Do(SegTree &res,SegTree res1,SegTree res2){
res.first = res1.first;
res.last = res2.last;
res.pl = res1.pl;
res.sl = res2.sl;
if(res1.pl == res1.len && res1.last < res2.first){
res.pl = res1.pl + res2.pl;
}
if(res2.sl == res2.len && res1.last < res2.first){
res.sl = res2.sl + res1.sl;
}
res.Max = max(res1.Max,res2.Max);
if(res1.last < res2.first){
res.Max = max(res.Max,res1.sl + res2.pl);
}
}

void updata(int rt,int a,int b,int val){
if(t[rt].l == a && t[rt].r == b){
Del(rt,val);
return ;
}
PushDown(rt);
int mid = t[rt].mid;
if(b <= mid)
updata(lson(rt),a,b,val);
else if(a > mid)
updata(rson(rt),a,b,val);
else{
updata(lson(rt),a,mid,val);
updata(rson(rt),mid+1,b,val);
}
PushUp(rt);
}

SegTree query(int rt,int a,int b){
if(t[rt].l == a && t[rt].r == b){
return t[rt];
}
PushDown(rt);
int mid = t[rt].mid;
if(b <= mid)
return query(lson(rt),a,b);
else if(a > mid)
return query(rson(rt),a,b);
else{
SegTree res1 = query(lson(rt),a,mid);
SegTree res2 = query(rson(rt),mid+1,b);
SegTree res = SegTree(a,b);
Do(res,res1,res2);
return res;
}
}

int main(){
int n,q,T;
scanf("%d",&T);
for(int cas = 1; cas <= T; cas++){
printf("Case #%d:\n",cas);
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--){
char op[5]; int a,b,val;
scanf("%s",op);
if(op[0] == 'a'){
scanf("%d%d%d",&a,&b,&val);
updata(1,a,b,val);
}
else{
scanf("%d%d",&a,&b);
SegTree res = query(1,a,b);
printf("%d\n",res.Max);
}
}
}
return 0;
}