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