Codeforces 1039E:Summer Oenothera Exhibition(LCT)
阿新 • • 發佈:2018-12-09
題解: 首先可以貪心解決單次詢問。
考慮優化,每個點有一個後繼,這個後繼在的時候,我們暴力修改,否則不管。 查詢直接在LCT上查詢次即可。
時間複雜度。當然可以繼續優化為,不過這份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');
}