BZOJ1112: [POI2008]砖块Klo(splay)

Description

N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.

Input

第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000

Output

最小的动作次数

Sample Input

5 3
3
9
2
3
1

Sample Output

2

解题思路:

主要是一个规律知道就好了:序列更改为中位数次数最小

证明吗?

去问数竞的吧

好了废话不多说。

相当于一个长度为k的yy出来的窗口在滑动,splay O(logn)维护中位数即可。

时间复杂度O(nlogn)

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 #define inp tr[tr[root].ch[1]].ch[0]
  9 using std::min;
 10 using std::abs;
 11 typedef long long lnt;
 12 struct trnt{
 13     int ch[2];
 14     int fa;
 15     int wgt;
 16     int num;
 17     lnt val;
 18     lnt sum;
 19 }tr[1000000],str;
 20 int n,k;
 21 int root;
 22 int top;
 23 int siz;
 24 int grv;
 25 lnt ans;
 26 lnt klo[1000000];
 27 int bin[1000000];
 28 bool whc(int spc)
 29 {
 30     return tr[tr[spc].fa].rs==spc;
 31 }
 32 void pushup(int spc)
 33 {
 34     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+tr[spc].num;
 35     tr[spc].sum=tr[spc].val*tr[spc].num+tr[lll].sum+tr[rrr].sum;
 36     return ;
 37 }
 38 void rotate(int spc)
 39 {
 40     int f=tr[spc].fa;
 41     bool k=whc(spc);
 42     tr[f].ch[k]=tr[spc].ch[!k];
 43     tr[spc].ch[!k]=f;
 44     tr[tr[f].fa].ch[whc(f)]=spc;
 45     tr[spc].fa=tr[f].fa;
 46     tr[f].fa=spc;
 47     tr[tr[f].ch[k]].fa=f;
 48     pushup(f);
 49     pushup(spc);
 50     return ;
 51 }
 52 void splay(int spc,int f)
 53 {
 54     while(tr[spc].fa!=f)
 55     {
 56         int ft=tr[spc].fa;
 57         if(tr[ft].fa==f)
 58         {
 59             rotate(spc);
 60             break;
 61         }
 62         if(whc(spc)^whc(ft))
 63             rotate(spc);
 64         else
 65             rotate(ft);
 66         rotate(spc);
 67     }
 68     if(!f)
 69         root=spc;
 70 }
 71 int place(int spc,int rnk)
 72 {
 73     if(tr[lll].wgt>=rnk)
 74         return place(lll,rnk);
 75     if(tr[spc].num+tr[lll].wgt>=rnk)
 76         return spc;
 77     return place(rrr,rnk-tr[spc].num-tr[lll].wgt);
 78 }
 79 int aa;
 80 void maxmin(int spc,int v)
 81 {
 82     if(!spc)
 83         return ;
 84     if(tr[spc].val<v)
 85     {
 86         aa=spc;
 87         return maxmin(rrr,v);
 88     }
 89     return maxmin(lll,v);
 90 }
 91 void minmax(int spc,int v)
 92 {
 93     if(!spc)
 94         return ;
 95     if(tr[spc].val>v)
 96     {
 97         aa=spc;
 98         return minmax(lll,v);
 99     }
100     return minmax(rrr,v);
101 }
102 void del(int &spc)
103 {
104     bin[++top]=spc;
105     tr[spc]=str;
106     spc=0;
107     return ;
108 }
109 int newp()
110 {
111     if(top)
112         return bin[top--];
113     return ++siz;
114 }
115 void ins(int v)
116 {
117     aa=0;
118     maxmin(root,v);
119     splay(aa,0);
120     aa=0;
121     minmax(root,v);
122     splay(aa,root);
123     if(inp)
124     {
125         tr[inp].num++;
126         tr[inp].wgt++;
127     }else{
128         inp=newp();
129         tr[inp].fa=tr[root].rs;
130         tr[inp].num=tr[inp].wgt=1;
131         tr[inp].val=v;
132     }
133     pushup(inp);
134     pushup(tr[root].rs);
135     pushup(root);
136     return ;
137 }
138 void Del(int v)
139 {
140     aa=0;
141     maxmin(root,v);
142     splay(aa,0);
143     aa=0;
144     minmax(root,v);
145     splay(aa,root);
146     tr[inp].num--;
147     if(!tr[inp].num)
148         del(inp);
149     else
150         pushup(inp);
151     pushup(tr[root].rs);
152     pushup(root);
153     return ;
154 }
155 void update()
156 {
157     splay(1,0);
158     splay(2,1);
159     int x=place(inp,grv);
160     splay(x,2);
161     int spc=inp;
162     ans=min(ans,abs(tr[lll].sum-tr[lll].wgt*tr[inp].val)+abs(tr[rrr].sum-tr[rrr].wgt*tr[inp].val));
163     return ;
164 }
165 int main()
166 {
167     root=1;
168     siz=2;
169     tr[root].val=-100;
170     tr[root].rs=2;
171     tr[2].val=0x3f3f3f3f3f3f3f3fll;
172     tr[2].fa=1;
173     scanf("%d%d",&n,&k);
174     grv=(k+1)>>1;
175     for(int i=1;i<=n;i++)
176         scanf("%lld",&klo[i]);
177     for(int i=1;i<=k;i++)
178         ins(klo[i]);
179     ans=0x7f7f7f7f7f7f7f7fll;
180     update();
181     for(int i=k+1;i<=n;i++)
182     {
183         Del(klo[i-k]);
184         ins(klo[i]);
185         update();
186     }
187     printf("%lld
",ans);
188     return 0;
189 }
190 
原文地址:https://www.cnblogs.com/blog-Dr-J/p/9672304.html