zoukankan      html  css  js  c++  java
  • [Baltic2004]sequence

    题目描述:

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

    样例输入

    7 9 4 8 20 14 15 18

    样例输出

    13

    提示

    所求的Z序列为6,7,8,13,14,15,18.

    R=13

    题解:

    考虑t1>=t2>=t3>=t4这种递减的情况,那么整个z只需取t数组的中位数即可。

    由于z是递增数列,不能全取一样的数。所以我们把t[i]-i;保证z数组就可以取一样的数了 且不会影响答案,因为t[i]-i的同时,求出来z[i]也是减了i的

    那么我们就采取分治的思想,把原数列分成m个递减区间,然后分别取中位数,使得该区间的差值尽量小.

    设X[i]为没个区间的中位数,那么如果X[i]<X[i-1]时不满足z[i]递增的题意,所以要合并,且合并后的答案会更优。(见网上的论文证明)

    以下是详细做法和证明:

    还有一个我的傻逼错误

    ldis()和rdis()没写return 居然函数没有返回值不warning,浪费了很久

    代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<cstdlib>
     7 using namespace std;
     8 const int N=1000005;
     9 typedef long long ll;
    10 ll gi()
    11 {
    12     ll str=0;char ch=getchar();
    13     while(ch>'9' || ch<'0')ch=getchar();
    14     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
    15     return str;
    16 }
    17 struct node
    18 {
    19     int dis,size,ls,rs;ll x;
    20     node *l,*r;
    21     int ldis(){return l?l->dis:0;}
    22     int rdis(){return r?r->dis:0;}
    23 }T[N];
    24 ll a[N];node *root[N],*pos=T;
    25 ll st[N],top=0;
    26 ll ans=0;
    27 void updata(node *&R)
    28 {
    29     if(R)R->size=(R->l?R->l->size:0)+(R->r?R->r->size:0)+1;
    30 }
    31 node *merge(node *p,node *q)
    32 {
    33     if(!p||!q){return p?p:q;}
    34     if(p->x<q->x)swap(p,q);
    35     if(p->ls>q->ls)p->ls=q->ls;
    36     if(p->rs<q->rs)p->rs=q->rs;
    37     p->r=merge(p->r,q);
    38     if(p->ldis()<p->rdis())swap(p->l,p->r);
    39     p->dis=p->rdis()+1;
    40     updata(p);
    41     return p;
    42 }
    43 void Delet(int x)
    44 {
    45     node *y=root[x]; 
    46     root[x]=merge(root[x]->r,root[x]->l);
    47     root[x]->ls=y->ls;root[x]->rs=y->rs;
    48     y->l=y->r=NULL;y->size=0;
    49 }
    50 int main()
    51 {
    52     int n=gi(),k;
    53     for(int i=1;i<=n;i++){
    54         a[i]=gi()-i;
    55         pos->l=pos->r=NULL;pos->x=a[i];pos->size=1;
    56         pos->ls=pos->rs=i;
    57         root[i]=pos;pos->dis=0;
    58         pos++;
    59     }
    60     int now;
    61     st[++top]=1;
    62     for(int i=2;i<=n;i++){
    63         now=i;
    64         while(top){
    65             k=st[top];
    66             if(root[k]->x>root[now]->x){
    67                 top--;
    68                 root[k]=merge(root[now],root[k]);
    69                 while((root[k]->size<<1)>(root[k]->rs-root[k]->ls+2))Delet(k);
    70                 now=k;
    71                 if(!top){
    72                     st[++top]=now;
    73                     break;
    74                 }
    75             }
    76             else{
    77                 st[++top]=now;
    78                 break;
    79             }
    80         }
    81     }
    82     while(top){
    83         k=st[top];top--;
    84         for(int i=root[k]->ls;i<=root[k]->rs;i++)ans+=abs(root[k]->x-a[i]);
    85     }
    86     cout<<ans;
    87     return 0;
    88 }
  • 相关阅读:
    poj 3243 Clever Y(BabyStep GiantStep)
    poj 2417 Discrete Logging
    poj 3481 Double Queue
    hdu 4046 Panda
    hdu 2896 病毒侵袭
    poj 1442 Black Box
    hdu 2815 Mod Tree
    hdu 3065 病毒侵袭持续中
    hdu 1576 A/B
    所有控件
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6840398.html
Copyright © 2011-2022 走看看