UOJ515 前进四(扫描线+势能线段树)
考虑以时间为下标,数组下标从 $n$ 至 $1$ 扫描,那么 $a_i$ 在 $t_1-t_2$ 时刻的值为 $val$ 对应的修改应为对 $t_1-t_2$ 区间取 $\min$。而查询操作对应的就是查询 $t$ 这个位置被更新了多少次。
考虑势能线段树维护。因为不同的 $val$ 不超过 $n+t$ 个,所以时间复杂度为 $O((n+t)\log t)$。
欸我怎么 85/97 啊?注意一下卡常点:
- 询问是单点查询,从上到下 pushdown 常数很大,要用 zkw 线段树的写法从下往上加;
- vector 插入是真的慢($n=10^6$ 时光插入就要0.8s),要手写链表;
- puhsup/pushdown 可以考虑手工内联;
- 各种奇奇怪怪的卡常技巧。
#include<cstdio> #define For(i,A,B) for(i=(A);i<=(B);++i) const int N=1000050; const int BUF=1<<23; char rB[BUF],*rS,*rT,wB[BUF],*wT=wB; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,BUF,stdin),rS==rT)?EOF:*rS++;} inline void flush(){fwrite(wB,1,wT-wB,stdout);wT=wB;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[15]; inline void wt(int x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } *wT++=x|48; while(l>=0)*wT++=buf[l--]|48; *wT++='\n'; } int mx[N<<2],mx2[N<<2],tag[N<<2],ps[N],s[N],chd[N],qhd[N],tim[N<<1],val[N<<1],nxt[N<<1],x,y,v,tot; inline int Max(int a,int b){return a>b?a:b;} inline void ins(int *hd,int x,int tm,int vl){ tim[++tot]=tm;val[tot]=vl;nxt[tot]=hd[x];hd[x]=tot; } void build(int o,int L,int R){ mx[o]=0x3f3f3f3f; if(L<R){ int lc=o<<1,rc=lc|1,M=L+R>>1; build(lc,L,M);build(rc,M+1,R); }else ps[L]=o; } void update(int o,int L,int R){ if(x<=L&&y>=R&&v>mx2[o]){ if(v<mx[o]){mx[o]=v;++tag[o];} return; } int lc=o<<1,rc=lc|1,M=L+R>>1; if(tag[o]){ int lc=o<<1,rc=lc|1; if(mx[o]<mx[lc]){mx[lc]=mx[o];tag[lc]+=tag[o];} if(mx[o]<mx[rc]){mx[rc]=mx[o];tag[rc]+=tag[o];} tag[o]=0; } if(x<=M)update(lc,L,M); if(y>M)update(rc,M+1,R); if(mx[lc]==mx[rc]){mx[o]=mx[lc];mx2[o]=Max(mx2[lc],mx2[rc]);} else if(mx[lc]>mx[rc]){mx[o]=mx[lc];mx2[o]=Max(mx2[lc],mx[rc]);} else{mx[o]=mx[rc];mx2[o]=Max(mx[lc],mx2[rc]);} } inline int query(int x){ int o=ps[x],s=tag[o],val=mx[o]; for(o>>=1;o;o>>=1)if(mx[o]<val){s+=tag[o];val=mx[o];} return s; } int main(){ int n=rd(),q=rd(),i,j,opt,ccnt=0,qcnt=-1; bool lq=0; For(i,1,n)ins(chd,i,0,rd()); while(q--){ opt=rd();x=rd(); if(opt==1){ if(lq){++ccnt;lq=0;} ins(chd,x,ccnt,rd()); }else{ ins(qhd,x,ccnt,++qcnt); lq=1; } } build(1,0,ccnt); for(i=n;i;--i){ for(y=ccnt,j=chd[i];j;j=nxt[j]){ if((x=tim[j])<=y){ v=val[j]; update(1,0,ccnt); } y=x-1; } for(j=qhd[i];j;j=nxt[j])s[val[j]]=query(tim[j]); } For(i,0,qcnt)wt(s[i]); flush(); return 0; }