1. 程式人生 > >Codeforces 1039E:Summer Oenothera Exhibition(LCT)

Codeforces 1039E:Summer Oenothera Exhibition(LCT)

傳送門

題解: 首先可以貪心O(n)解決單次詢問。

考慮優化,每個點有一個後繼,這個後繼在n的時候,我們暴力修改,否則不管。 查詢直接在LCT上查詢O(n)次即可。

時間複雜度O(nnlogn)。當然可以繼續優化為O(n53+n43logn),不過這份LCT的程式碼比rk2快了接近一倍。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;

const int RLEN=1<<18
|1; inline char nc() { static char ibuf[RLEN],*ib,*ob; (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ib==ob) ? -1 : *ib++; } inline int rd() { char ch=nc(); int i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<1)+(i<<3
)+ch-'0'; ch=nc();} return i*f; } inline void W(int x) { static int buf[50]; if(!x) {putchar('0'); return;} if(x<0) {putchar('-'); x=-x;} while(x) {buf[++buf[0]]=x%10; x/=10;} while(buf[0]) {putchar(buf[buf[0]--]+'0');} } const int N=1e5+50, B=30, L=18; int n,w,q,ans[N],nxt[N]; int lg[N],x[N],rmq_mx[N][20
],rmq_mn[N][20]; vector <pii> det; vector <pii> ask; struct node { node *fa,*lc,*rc; int id,sze; node() : fa(NULL),lc(NULL),rc(NULL),sze(0) {} inline void upt() {sze=(lc?lc->sze:0)+(rc?rc->sze:0)+1;} } *pos[N]; inline bool isroot(node *x) {return (!x->fa) || (x->fa->lc!=x && x->fa->rc!=x);} inline bool which(node *x) {return (x->fa->lc==x);} inline void rotate(node *x) { node *y=x->fa, *z=y->fa; if(!isroot(y)) (z->lc==y ? z->lc : z->rc)=x; x->fa=z; y->fa=x; if(y->lc==x) { node *b=x->rc; x->rc=y; y->lc=b; if(b) b->fa=y; } else { node *b=x->lc; x->lc=y; y->rc=b; if(b) b->fa=y; } y->upt(); x->upt(); } inline void splay(node *x) { while(!isroot(x)) { node *y=x->fa; if(!isroot(y)) { if(which(y)==which(x)) rotate(y); else rotate(x); } rotate(x); } } inline void access(node *x) { for(node *y=NULL;x;y=x,x=x->fa) { splay(x); x->rc=y; x->upt(); } } inline void cut(node *x,node *f) { access(f); splay(x); x->fa=NULL; } inline void link(node *x,node *f) { x->fa=f; } inline void modify(int lim) { static int p=0; while(p<det.size() && det[p].first<=lim) { int u=det[p++].second; if(nxt[u]+u>n) continue; else if((++nxt[u])==B) { cut(pos[u],pos[u+nxt[u]]); } else { cut(pos[u],pos[u+nxt[u]]); link(pos[u],pos[u+nxt[u]+1]); } } } inline node* getroot(node *x) { while(x->lc) x=x->lc; splay(x); return x; } inline int find_nxt(int now,int lim) { int mx=x[now], mn=x[now]; for(int i=lg[n-now+1];~i && now<=n;i--) { if((now+(1<<i)-1<=n) && max(mx,rmq_mx[now][i])-min(mn,rmq_mn[now][i])<=lim) { mx=max(mx,rmq_mx[now][i]); mn=min(mn,rmq_mn[now][i]); now+=(1<<i); } } return now; } inline int query(int lim) { int now=1, cnt=0; while(now<=n) { access(pos[now]); splay(pos[now]); cnt+=pos[now]->sze-1; now=getroot(pos[now])->id; if(now!=n+1) ++cnt, now=find_nxt(now,lim); } return cnt; } int main() { n=rd(), w=rd(), q=rd(); lg[1]=0; for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1; for(int i=1;i<=n;i++) rmq_mn[i][0]=rmq_mx[i][0]=x[i]=rd(); for(int i=1;i<=lg[n];i++) for(int j=1;j+(1<<i)-1<=n;++j) rmq_mn[j][i]=min(rmq_mn[j][i-1],rmq_mn[j+(1<<(i-1))][i-1]), rmq_mx[j][i]=max(rmq_mx[j][i-1],rmq_mx[j+(1<<(i-1))][i-1]); pos[n+1]=new node(); pos[n+1]->id=n+1; for(int i=n;i>=1;i--) { pos[i]=new node(); pos[i]->fa=pos[i+1]; pos[i]->sze=1; pos[i]->id=i; } for(int i=1;i<=n;i++) { int mx=x[i], mn=x[i]; for(int j=1;j<=B && i+j<=n;j++) { mx=max(mx,x[i+j]); mn=min(mn,x[i+j]); det.push_back(pii(mx-mn,i)); } } sort(det.begin(),det.end()); for(int i=1;i<=q;i++) { int k=w-rd(); ask.push_back(pii(k,i)); } sort(ask.begin(),ask.end()); for(int i=0;i<ask.size();++i) { modify(ask[i].first); ans[ask[i].second]=query(ask[i].first)-1; } for(int i=1;i<=q;i++) W(ans[i]), putchar('\n'); }