https://www.luogu.com.cn/problem/P2894
线段树区间连续最大的1的个数,加上区间修改,lazy覆盖。虽然不难,写出来还是很interesting的。。
具体看代码吧
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+11;
int ans[4*maxn],L[4*maxn],R[4*maxn];
int lazy[maxn*4];
void up(int node,int be,int en){
int l = node*2;
int r = node*2+1;
int mid = be + en >> 1;
ans[node] = max(ans[l],ans[r]);
ans[node] = max(ans[node],L[r] + R[l]);
L[node] = L[l];
if(mid - be + 1 == L[l]) L[node] = mid - be + 1 + L[r];
R[node] = R[r];
if(en - mid == R[r]) R[node] = en - mid + R[l];
}
int push(int node,int be,int en){
int mid = be + en >> 1;
int l = node * 2;
int r = node * 2 + 1;
if(lazy[node]){
ans[l] = L[l] = R[l] = (mid - be + 1)*(lazy[node]-1);
ans[r] = L[r] = R[r] = (en - mid)*(lazy[node]-1);
lazy[l] = lazy[r] = lazy[node];
lazy[node] = 0;
}
return 0;
}
int update(int node,int be,int en,int LL,int RR,int val){//直接用1覆盖
int mid = be + en >> 1;
int l = node*2;
int r = node*2 + 1;
if(LL <= be && en <= RR){
lazy[node] = val;
ans[node] = L[node] = R[node] = (en - be + 1)*(val-1);
return 0;
}
push(node,be,en);
if(LL <= mid) update(l,be,mid,LL,RR,val);
if(RR > mid) update(r,mid+1,en,LL,RR,val);
up(node,be,en);
return 0;
}
int id = 0;
int ask(int node,int be,int en,int x){
int mid = be + en >> 1;
int l = node*2;
int r = node*2 + 1;
if(be == en){
id = be;
return 0;
}
push(node,be,en);
if(ans[l] >= x){
ask(l,be,mid,x);
up(node,be,en);
}
else if(R[l] + L[r] >= x){
id = mid - R[l] + 1;
return 0;
}
else if(ans[r] >= x){
ask(r,mid+1,en,x);
up(node,be,en);
}
else{
return 0;
}
return 0;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
update(1,1,n,1,n,2);
id= 0 ;
while(m--){
int op;
scanf("%d",&op);
if(op == 1){
int x;
scanf("%d",&x);
id = 0;
ask(1,1,n,x);
if(id != 0) update(1,1,n,id,id+x-1,1);
printf("%lld
",id);
}
else{
int x,y;
scanf("%d %d",&x,&y);
update(1,1,n,x,x + y - 1,2);
}
}
return 0;
}