zoukankan      html  css  js  c++  java
  • 【左偏树+贪心】BZOJ1367-[Baltic2004]sequence

    【题目大意】

    给定一个序列t1,t2,...,tn ,求一个递增序列z1<z2<...<zn , 使得R=|t1z1|+|t2z2|+...+|tnzn| 的值最小。本题中,我们只需要求出这个最小的R值。

    【思路】

    -这个比加延迟标记的左偏树调试得还久……WA到死……

    如果ti是递增的,我们只需要取zi=ti;

    如果ti是递减的,我们只需要取ti的中位数。

    所以我们将ti分割成若干个区间,维护每个区间的中位数。对于[L,R]的区间,我们存放[L,(L+R)/2]在堆中。具体如下操作:

    (1)加入ti,将它作为一个单独的区间。

    (2)比较前一个区间的中位数(即当前栈顶的最大值)和当前区间的中位数,如果前者小于后者,就将后者压入栈中。否则将前者弹出,和后者合并。注意的是如果两个区间的大小均为奇数(注意这里说的是区间大小,即L-R+1,而不是维护中位数的堆的大小),比如3和5合并,我们只需要存4个数字,而直接合并堆中存了5个,所以弹出堆顶。

    (3)把合并后的堆作为当前区间,继续操作。

    某种意义上的贪心思想。

    我用的是左偏树,在左偏树里同时记录了L、R、size。

    不过这样操作只会得到不下降,而不是递增。据说一开始输入t[i]时,t[i]-=i即可,没有会到意思orz

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<cmath>
      7 using namespace std;
      8 const int MAXN=1000000+50;
      9 typedef long long ll;
     10 struct node
     11 {
     12     int key,dis,size;
     13     int lson,rson,father;
     14     int L,R;
     15 
     16 }ltree[MAXN];
     17 int n,z[MAXN];
     18 stack<int> S;
     19 
     20 void pushup(int x)
     21 {
     22     int l=ltree[x].lson,r=ltree[x].rson;
     23     ltree[x].size=1+ltree[l].size+ltree[r].size;
     24 } 
     25 
     26 void build(int rt,int x)
     27 {
     28     ltree[rt].key=x;
     29     ltree[rt].dis=(rt==0)?-1:0;
     30     ltree[rt].size=(rt==0)?0:1;
     31     //不要忘了当Rt=0的时候size为0 
     32     ltree[rt].lson=ltree[rt].rson=0;
     33     ltree[rt].father=ltree[rt].L=ltree[rt].R=rt;
     34 }
     35 
     36 int merge(int x,int y)
     37 {
     38     if (x==0 || y==0) return (x+y);
     39     if (ltree[x].key<ltree[y].key) swap(x,y);
     40     ltree[x].L=min(ltree[x].L,ltree[y].L);
     41     ltree[x].R=max(ltree[x].R,ltree[y].R);
     42     ltree[x].rson=merge(ltree[x].rson,y);
     43     int &l=ltree[x].lson,&r=ltree[x].rson;
     44     if (ltree[l].dis<ltree[r].dis) swap(l,r);
     45     if (r==0) ltree[x].dis=0;
     46         else ltree[x].dis=ltree[r].dis+1;
     47     pushup(x);
     48     return x;
     49 }
     50 
     51 int del(int rt)
     52 {
     53     int l=ltree[rt].lson,r=ltree[rt].rson;
     54     ltree[rt].dis=0;
     55     ltree[rt].size=1;
     56     ltree[rt].lson=ltree[rt].rson=0;
     57     int ret=merge(l,r);
     58     ltree[ret].L=ltree[rt].L;
     59     ltree[ret].R=ltree[rt].R;
     60     return ret;
     61 }
     62 
     63 void init()
     64 {
     65     scanf("%d",&n);
     66     for (int i=1;i<=n;i++) scanf("%d",&z[i]),z[i]-=i;
     67     for (int i=1;i<=n;i++) build(i,z[i]);
     68     build(0,0);
     69 } 
     70 
     71 void solve()
     72 {
     73     int before=z[1];
     74     S.push(1);
     75     for (int i=2;i<=n;i++)
     76     {
     77         int now=i;
     78         while (!S.empty())
     79         {
     80             int tail=S.top();
     81             if (ltree[now].key<ltree[tail].key)
     82             {
     83                 S.pop();
     84                 int tmp=merge(tail,now);
     85                 now=tmp;
     86                 while (ltree[now].size*2>(ltree[now].R-ltree[now].L+2)) now=del(now);
     87                 //不要忘记了这里是ltree[now].R-ltree[now].L+2,一开始写成了+1 
     88                 if (S.empty())
     89                 {
     90                     S.push(now);
     91                     break;
     92                 }
     93             }
     94             else
     95             {
     96                 S.push(now);
     97                 break;
     98             }
     99         }
    100     }
    101     ll ans=0;
    102     while (!S.empty())
    103     {
    104         int now=S.top();S.pop();
    105         for (int i=ltree[now].L;i<=ltree[now].R;i++) ans+=abs(z[i]-ltree[now].key);
    106     }
    107     printf("%lld",ans);
    108 }
    109 
    110 int main()
    111 {
    112     init();
    113     solve();
    114     return 0;
    115 }
  • 相关阅读:
    将博客搬至CSDN
    IDEA安装对应版本的lombok才生效
    shift键复选dataGrid的记录时多余的文本总被选择了。
    git 导出新修改的文件
    svn老鸟转用git必须理解的概念
    java中Long类型和long类型的大小比较
    eclipse反编译插件jadClipse安装使用教程
    js闭包
    java泛型讲解
    常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5836427.html
Copyright © 2011-2022 走看看