第一次ac的splay纪念(a题量跻身本校前十祭!!!)
代码解决的是求中位数的问题具体见poi2008 block
#include<bits/stdc++.h> #define M 1000000 using namespace std; int size[M],ch[M][2],cnt[M],sum[M],f[M],key[M],sz,root; int h[M]; void clear(int x){size[x]=ch[x][0]=ch[x][1]=cnt[x]=f[x]=key[x]=key[x]=0;} int get(int x){return ch[f[x]][1]==x;} void update(int x){ if(x){ size[x]=cnt[x];sum[x]=cnt[x]*key[x]; if(ch[x][0]) size[x]+=size[ch[x][0]],sum[x]+=sum[ch[x][0]]; if(ch[x][1]) size[x]+=size[ch[x][1]],sum[x]+=sum[ch[x][1]]; } } void rotate(int x){ int fa=f[x],gf=f[fa],which=get(x); ch[fa][which]=ch[x][which^1];f[ch[fa][which]]=fa; f[fa]=x;ch[x][which^1]=fa; f[x]=gf; if(gf) ch[gf][ch[gf][1]==fa]=x; update(fa),update(x); } void splay(int x){ for(int fa;fa=f[x];rotate(x)) if(f[fa]) rotate(get(x)==get(fa)?fa:x); root=x; } void insert(int v){ if(root==0){sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;key[sz]=v;size[sz]=cnt[sz]=1;sum[sz]=v;root=sz;return;} int now=root,fa=0; while(1){ if(key[now]==v){ cnt[now]++;update(now);update(fa);splay(now);break; } fa=now; now=ch[now][key[now]<v]; if(now==0){ sz++; ch[sz][0]=ch[sz][1]=0; key[sz]=v; size[sz]=1;cnt[sz]=1; f[sz]=fa;ch[fa][key[fa]<v]=sz; update(fa); splay(sz); break; } } } int find(int v){ int ans=0,now=root; while(1){ if(v<key[now]) now=ch[now][0]; else{ ans+=ch[now][0]?size[ch[now][0]]:0; if(v==key[now]){splay(now);return ans+1;} ans+=cnt[now]; now=ch[now][1]; } } } int findx(int x){ int now=root; while(1){ if(ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0]; else{ int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now]; if(x<=temp) return now; x-=temp;now=ch[now][1]; } } } int pre(){ int now=ch[root][0]; while(ch[now][1])now=ch[now][1]; return now; } int next(){ int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } void del(int x){ int whatever=find(x); if(cnt[root]>1){cnt[root]--;return;} if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;} if(!ch[root][0]){ int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return; } else if(!ch[root][1]){ int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return; } int leftbig=pre(),oldroot=root; splay(leftbig); f[ch[oldroot][1]]=root; ch[root][1]=ch[oldroot][1]; clear(oldroot); update(root); return; } int main(){ int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&h[i]); for(int i=1;i<=k;i++) insert(h[i]); int p=(k+1)/2; int tmp=findx(p); splay(tmp); long long ans=size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]]; for(int i=2;i<=n-k+1;i++){ del(h[i-1]);insert(h[i+k-1]); tmp=findx(p); splay(tmp); ans=min((long long)size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]],ans); } printf("%lld",ans); }
月光抽出3个月祭