UOJ#515. 【UR #19】前进四 离线+吉司机线段树
我们发现依次修改影响的是时间线段树一段区间要取 min,这个用吉司机线段树维护就好了.
具体地,我们记录一个 tag 标记,然后下传条件是 mx[now]<mx[lson] 或 mx[now]<mx[rson].
这道题卡常,最好不要用 vector 来存储操作.
code:
#include <bits/stdc++.h> #define N 2000009 #define ll long long #define lson now<<1 #define rson now<<1|1 #define inf 2000000009 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int n,m,Q; int mx[N<<2],se[N<<2],tag[N<<2],a[N]; void pushup(int now) { mx[now]=max(mx[lson],mx[rson]); if(mx[lson]==mx[rson]) se[now]=max(se[lson],se[rson]); else if(mx[lson]<mx[rson]) se[now]=max(mx[lson],se[rson]); else se[now]=max(mx[rson],se[lson]); } void pushdown(int now) { if(mx[lson]>mx[now]) mx[lson]=mx[now],tag[lson]+=tag[now]; if(mx[rson]>mx[now]) mx[rson]=mx[now],tag[rson]+=tag[now]; tag[now]=0; } void update(int l,int r,int now,int L,int R,int v) { if(mx[now]<=v) return; if(l>=L&&r<=R&&se[now]<v) { mx[now]=v,++tag[now]; return; } pushdown(now); int mid=(l+r)>>1; if(L<=mid) update(l,mid,lson,L,R,v); if(R>mid) update(mid+1,r,rson,L,R,v); pushup(now); } int query(int l,int r,int now,int p) { if(l==r) return tag[now]; int mid=(l+r)>>1; pushdown(now); if(p<=mid) return query(l,mid,lson,p); else return query(mid+1,r,rson,p); } void build(int l,int r,int now) { mx[now]=inf,se[now]=-inf; if(l==r) return; int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); } int Ans[N]; vector<int>q[N]; struct data { int x,t; data(int x=0,int t=0):x(x),t(t){} bool operator<(const data b) const { return t<b.t; } }er[N]; int hd[N],nex[N],edges; void add(int u,data e) { nex[++edges]=hd[u],hd[u]=edges,er[edges]=e; } char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char c; while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x; } int main() { // setIO("input"); int x,y,z; n=rd(),m=rd(); for(int i=1;i<=n;++i) a[i]=rd(),add(i,data(a[i],0)); for(int i=1;i<=m;++i) { x=rd(); if(x==1) y=rd(),z=rd(),add(y,data(z,i)); // z 时刻开始生效 if(x==2) y=rd(),q[y].push_back(i); } build(0,m,1); for(int i=n;i>=1;--i) { int pr=m; for(int j=hd[i];j;j=nex[j]) { data e=er[j]; int r=pr,l=e.t; update(0,m,1,l,r,e.x); pr=e.t-1; } for(int j=0;j<q[i].size();++j) Ans[q[i][j]]=query(0,m,1,q[i][j]); } for(int i=1;i<=m;++i) if(Ans[i]) printf("%d\n",Ans[i]); return 0; }