bzoj1112[POI2008]砖块Klo*

bzoj1112[POI2008]砖块Klo

题意:

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

posted @ 2016-08-16 22:30  YuanZiming  阅读(152)  评论(0编辑  收藏  举报