传送门:https://www.luogu.com.cn/problem/P4314
题意:
给出 T 个数,E 个操作(T,E ≤10^5):
Q X Y:询问从 X 到 Y 的当前最大值
A X Y:询问从 X 到 Y 的历史最大值(出现过的最大数
P X Y Z:将 X 到 Y 这段区间加 Z
C X Y Z:将 X 到 Y 这段区间赋值为 Z
这个题,第一反应就是线段树
如果你是信心满满的用当前最大值及当前的标记维护历史最大值,你就会wa掉了
仔细想想这个历史最大值,如果按照最初的写法,先add,再cover,那么当前sum还没有更新sum+add就被覆盖了,历史最大值就不准确了
但你是不是又想在add之前把所有标记下放??
这样的话lazy标记就失去意义了,时间复杂度翻倍的上升,会 tle8个点 应该
呐 这个标记的方式就很巧妙了
struct node
{
int l,r,add,cov,sum,evsum,evadd,evcov,is_cov;
}tree[maxn*4];
基本的元素有l,r,add,cov
我们后添加的有 evsum(历史最大值)evadd(历史添加的最大值),evcov(历史覆盖最大值),is_cov(是否被覆盖过)
我们在下放标记更新sum的同时 用evxxx继续更新evsum
而且是实时下放标记,没有判断条件
重点是push_down,如何下放标记
分类讨论
1 加操作 对于他的两个儿子
如果被覆盖过,那么覆盖cov之后再加add,就相当于是覆盖了cov+add,更新evcov,evsum
//左儿子为例
tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd); tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd); tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add; tree[now<<1].add=0;
如果没有覆盖过,那就是加上一个add 更新evadd,evsum
//左儿子为例
tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd); tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd);
tree[now<<1].add+=tree[now].add;
tree[now<<1].sum+=tree[now].add;
记得清空标记
2 覆盖操作 对于他的两个儿子
如果被覆盖过,覆盖了cov,同时取最大值更新evcov,evsum
如果没有被覆盖过,把is_cov标记为1,把cov覆盖上去,更新evcov,evsum
if(tree[now<<1].is_cov)//以左儿子为例 { tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov); } else { tree[now<<1].is_cov=1; tree[now<<1].evcov=tree[now].evcov; } tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov); tree[now<<1].cov=tree[now<<1].sum=tree[now].cov; tree[now<<1].add=0;
关于怎么覆盖值得好好考虑,再就是要认清楚,他的本质是同时更新sum和evsum,把他们分开 自己考虑自己的就不会乱
对于sum的更新就正常来就好了,每次的cover操作过后add也就该请零了
240+行,这可真是我写除了模拟的最长代码,破了前天的记录
虽然东西有点多,但思路很清晰
仔细一点争取不用debug,不然绝对会崩溃的 (;´д`)ゞ
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define lowbit(a) ((a) & -(a)) 5 #define clean(a, b) memset(a, b, sizeof(a)) 6 const int inf = 0x3f3f3f3f; 7 const int maxn = 1e5 + 10; 8 int _; 9 10 ///////////////////////////////////////////////////////////////// 11 char s[10]; 12 int a[maxn]; 13 struct node 14 { 15 int l,r,add,cov,sum,evsum,evadd,evcov,is_cov; 16 }tree[maxn*4]; 17 void build(int l,int r,int now) 18 { 19 tree[now].l=l; 20 tree[now].r=r; 21 tree[now].sum=tree[now].evsum=-inf; 22 if(l==r) 23 { 24 tree[now].sum=a[l]; 25 tree[now].evsum=a[l]; 26 return ; 27 } 28 int mid=(l+r)>>1; 29 build(l,mid,now<<1); 30 build(mid+1,r,now<<1|1); 31 tree[now].evsum=tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum); 32 } 33 void push_down_add(int now) 34 { 35 if(tree[now<<1].is_cov) 36 { 37 tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd); 38 tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd); 39 tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add; 40 tree[now<<1].add=0; 41 } 42 else 43 { 44 tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd); 45 tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd); 46 tree[now<<1].add+=tree[now].add; 47 tree[now<<1].sum+=tree[now].add; 48 } 49 50 if(tree[now<<1|1].is_cov) 51 { 52 tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now<<1|1].cov+tree[now].evadd); 53 tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].cov+tree[now].evadd); 54 tree[now<<1|1].sum=tree[now<<1|1].cov=tree[now<<1|1].cov+tree[now].add; 55 tree[now<<1|1].add=0; 56 } 57 else 58 { 59 tree[now<<1|1].evadd=max(tree[now<<1|1].evadd,tree[now<<1|1].add+tree[now].evadd); 60 tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].sum+tree[now].evadd); 61 tree[now<<1|1].add+=tree[now].add; 62 tree[now<<1|1].sum+=tree[now].add; 63 } 64 65 tree[now].add=tree[now].evadd=0; 66 67 } 68 void push_down_cover(int now) 69 { 70 if(tree[now].is_cov) 71 { 72 if(tree[now<<1].is_cov) 73 { 74 tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov); 75 } 76 else 77 { 78 tree[now<<1].is_cov=1; 79 tree[now<<1].evcov=tree[now].evcov; 80 } 81 tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov); 82 tree[now<<1].cov=tree[now<<1].sum=tree[now].cov; 83 tree[now<<1].add=0; 84 85 if(tree[now<<1|1].is_cov) 86 { 87 tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now].evcov); 88 } 89 else 90 { 91 tree[now<<1|1].is_cov=1; 92 tree[now<<1|1].evcov=tree[now].evcov; 93 } 94 tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now].evcov); 95 tree[now<<1|1].cov=tree[now<<1|1].sum=tree[now].cov; 96 tree[now<<1|1].add=0; 97 98 tree[now].is_cov=tree[now].cov=tree[now].evcov=0; 99 } 100 } 101 void push_down(int now) 102 { 103 push_down_add(now); 104 push_down_cover(now); 105 } 106 void update(int l,int r,int x,int now) 107 { 108 if(l==tree[now].l&&r==tree[now].r) 109 { 110 if(tree[now].is_cov) 111 { 112 tree[now].evcov=max(tree[now].evcov,x); 113 } 114 else 115 { 116 tree[now].is_cov=1; 117 tree[now].evcov=x; 118 } 119 tree[now].evsum=max(tree[now].evsum,x); 120 tree[now].cov=tree[now].sum=x; 121 tree[now].add=0; 122 return ; 123 } 124 push_down(now); 125 int mid=(tree[now].l+tree[now].r)>>1; 126 if(r<=mid) update(l,r,x,now<<1); 127 else if(l>mid) update(l,r,x,now<<1|1); 128 else 129 { 130 update(l,mid,x,now<<1); 131 update(mid+1,r,x,now<<1|1); 132 } 133 tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum); 134 tree[now].evsum=max(tree[now].evsum,tree[now].sum); 135 } 136 void addition(int l,int r,int x,int now) 137 { 138 if(l==tree[now].l&&r==tree[now].r) 139 { 140 if(tree[now].is_cov) 141 { 142 tree[now].evcov=max(tree[now].evcov,tree[now].cov+x); 143 tree[now].evsum=max(tree[now].evsum,tree[now].cov+x); 144 tree[now].cov=tree[now].sum=tree[now].cov+x; 145 tree[now].add=0; 146 } 147 else 148 { 149 tree[now].evadd=max(tree[now].evadd,tree[now].add+x); 150 tree[now].evsum=max(tree[now].evsum,tree[now].sum+x); 151 tree[now].add+=x; 152 tree[now].sum+=x; 153 } 154 return ; 155 } 156 push_down(now); 157 int mid=(tree[now].l+tree[now].r)>>1; 158 if(r<=mid) addition(l,r,x,now<<1); 159 else if(l>mid) addition(l,r,x,now<<1|1); 160 else 161 { 162 addition(l,mid,x,now<<1); 163 addition(mid+1,r,x,now<<1|1); 164 } 165 tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum); 166 tree[now].evsum=max(tree[now].evsum,tree[now].sum); 167 } 168 int query(int l,int r,int now) 169 { 170 if(l==tree[now].l&&r==tree[now].r) 171 { 172 return tree[now].sum; 173 } 174 push_down(now); 175 int mid=(tree[now].l+tree[now].r)>>1; 176 int maxx=-inf; 177 if(r<=mid) maxx=max(maxx,query(l,r,now<<1)); 178 else if(l>mid) maxx=max(maxx,query(l,r,now<<1|1)); 179 else 180 { 181 maxx=max(maxx,query(l,mid,now<<1)); 182 maxx=max(maxx,query(mid+1,r,now<<1|1)); 183 } 184 return maxx; 185 } 186 int querymax(int l,int r,int now) 187 { 188 if(l==tree[now].l&&r==tree[now].r) 189 { 190 return tree[now].evsum; 191 } 192 push_down(now); 193 int mid=(tree[now].l+tree[now].r)>>1; 194 int maxx=-inf; 195 if(r<=mid) maxx=max(maxx,querymax(l,r,now<<1)); 196 else if(l>mid) maxx=max(maxx,querymax(l,r,now<<1|1)); 197 else 198 { 199 maxx=max(maxx,querymax(l,mid,now<<1)); 200 maxx=max(maxx,querymax(mid+1,r,now<<1|1)); 201 } 202 return maxx; 203 } 204 ///////////////////////////////////////////////////////////////// 205 int main() 206 { 207 // freopen("in.in","r",stdin); 208 int t,q; 209 scanf("%d",&t); 210 for(int i=1;i<=t;i++) 211 { 212 scanf("%d",&a[i]); 213 } 214 build(1,t,1); 215 scanf("%d",&q); 216 for(int i=1;i<=q;i++) 217 { 218 scanf("%s",s); 219 int x,y,z; 220 if(s[0]=='Q')//the max 221 { 222 scanf("%d%d",&x,&y); 223 int ans=query(x,y,1); 224 printf("%d ",ans); 225 } 226 if(s[0]=='A')//Ever largest 227 { 228 scanf("%d%d",&x,&y); 229 int ans=querymax(x,y,1); 230 printf("%d ",ans); 231 } 232 if(s[0]=='P') 233 { 234 scanf("%d%d%d",&x,&y,&z); 235 addition(x,y,z,1); 236 } 237 if(s[0]=='C') 238 { 239 scanf("%d%d%d",&x,&y,&z); 240 update(x,y,z,1); 241 } 242 } 243 return 0; 244 }