题意:
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:丢掉某柱砖的一块砖。给某柱加上一块砖,现在希望用最小次数的动作完成任务。N≤100000
题解:
设一个区间长度为k,其中位数为a,比a小的元素个数为b,和为c;比a大的元素个数为d,和为e。则题目要求维护一个长度为k的滑动窗口,能求出它的b*a-c+e-d*a。故用一个维护sum,size两个值的treap来维护。然而似乎我想复杂了?比所有人代码都大1k!注意要开long long。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdlib> 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define maxn 100010 7 #define ll long long 8 #define qs(x,y) qs(x,y) 9 #define qb(x,y) qb(x,y) 10 #define qss(x,y) qss(x,y) 11 #define qbs(x,y) qbs(x,y) 12 using namespace std; 13 14 inline int read(){ 15 char ch=getchar(); int f=1,x=0; 16 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 17 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 18 return f*x; 19 } 20 int ch[maxn][2],sz[maxn],cnt[maxn],rnd[maxn],n,k,tot,root; ll a[maxn],sm[maxn],v[maxn],ans; 21 void update(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x],sm[x]=sm[ch[x][0]]+sm[ch[x][1]]+v[x]*cnt[x];} 22 void rotate(int &x,bool a){int y=ch[x][a]; ch[x][a]=ch[y][!a]; ch[y][!a]=x; update(x); update(y); x=y;} 23 void ins(int &x,ll val){ 24 if(!x){x=++tot; v[x]=sm[x]=val; rnd[x]=rand(); ch[x][0]=ch[x][1]=0; sz[x]=cnt[x]=1; return;} 25 if(v[x]==val){cnt[x]++; sz[x]++; sm[x]+=val; return;} 26 if(val<v[x]){ins(ch[x][0],val); update(x); if(rnd[ch[x][0]]<rnd[x])rotate(x,0); return;} 27 if(val>v[x]){ins(ch[x][1],val); update(x); if(rnd[ch[x][1]]<rnd[x])rotate(x,1); return;} 28 } 29 void del(int &x,ll val){ 30 if(v[x]==val){ 31 if(cnt[x]>1){cnt[x]--; sz[x]--; sm[x]-=val; return;} 32 else{ 33 if(!ch[x][0]||!ch[x][1])x=ch[x][0]+ch[x][1]; 34 else{ 35 if(rnd[ch[x][0]]<rnd[ch[x][1]])rotate(x,0),del(ch[x][1],val),update(x); 36 else rotate(x,1),del(ch[x][0],val),update(x); 37 } 38 return; 39 } 40 } 41 if(val<v[x]){del(ch[x][0],val); update(x); return;} 42 if(val>v[x]){del(ch[x][1],val); update(x); return;} 43 } 44 int find(int x,int k){ 45 if(k>sz[ch[x][0]]&&k<=sz[ch[x][0]]+cnt[x])return x; 46 if(k<=sz[ch[x][0]])return find(ch[x][0],k); 47 if(k>sz[ch[x][0]]+cnt[x])return find(ch[x][1],k-sz[ch[x][0]]-cnt[x]); 48 } 49 ll qs(int x,ll val){ 50 if(val<v[x])return qs(ch[x][0],val); 51 if(val==v[x])return sm[ch[x][0]]; 52 if(val>v[x])return sm[x]-sm[ch[x][1]]+qs(ch[x][1],val); 53 } 54 ll qb(int x,ll val){ 55 if(val>v[x])return qb(ch[x][1],val); 56 if(val==v[x])return sm[ch[x][1]]; 57 if(val<v[x])return sm[x]-sm[ch[x][0]]+qb(ch[x][0],val); 58 } 59 int qss(int x,ll val){ 60 if(val<v[x])return qss(ch[x][0],val); 61 if(val==v[x])return sz[ch[x][0]]; 62 if(val>v[x])return sz[x]-sz[ch[x][1]]+qss(ch[x][1],val); 63 } 64 int qbs(int x,ll val){ 65 if(val>v[x])return qbs(ch[x][1],val); 66 if(val==v[x])return sz[ch[x][1]]; 67 if(val<v[x])return sz[x]-sz[ch[x][0]]+qbs(ch[x][0],val); 68 } 69 int main(){ 70 n=read(); k=read(); inc(i,1,n)a[i]=read(); inc(i,1,k)ins(root,a[i]); int l=1,r=k; 71 ans=1LL*100000000000; 72 while(1){ 73 ll x=v[find(root,(k>>1)+1)]; 74 ans=min(ans,x*qss(root,x)-qs(root,x)+qb(root,x)-qbs(root,x)*x); 75 del(root,a[l]); l++; r++; if(r>n)break; ins(root,a[r]); 76 } 77 printf("%lld",ans); return 0; 78 }
20160814