码迷,mamicode.com
首页 > 其他好文 > 详细

[poj] 3666 Making the Grade

时间:2017-11-26 12:44:16      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:修改   read   update   std   ace   val   name   merge   swa   

原题

左偏树裸题(也可以用dp做)

对于一段有连续性的不合法区间,把他们全都变成中位数显然是最好的。
假如我们要实现连续不下降,那么:
对于后一段区间的中位数比前一段的中位数小,那么把这两段区间合并,全部修改为这两段区间的中位数,否则的话就不用管。
假如我们要实现连续不上升,那么我们把小于号改为大于号就好了……

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 2020
using namespace std;
int n,a[N],ans,tmp,q[N],b[N],l,now;
struct node
{
    node *ls,*rs;
    int val,dist,siz;
    node(): ls(NULL),rs(NULL),val(0),dist(0),siz(0){}
    node(int x): ls(NULL),rs(NULL),val(x),dist(0),siz(1){}
    node* update()
    {
        if (!ls || ls->dist<rs->dist) swap(ls,rs);
        dist=rs?rs->dist+1:0;
        siz=(ls?ls->siz:0)+(rs?rs->siz:0)+1;
        return this;
    }
}*tre[N];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ;
    if (j==‘-‘) fu=-1,j=getchar();
    for (;j>=‘0‘ && j<=‘9‘;j=getchar()) ans*=10,ans+=j-‘0‘;
    return ans*fu;
}

node* merge(node *x,node*y)
{
    if (!x) return y;
    if (!y) return x;
    if (x->val<y->val) swap(x,y);
    x->rs=merge(x->rs,y);
    return x->update();
}

void pop(node *&x,int t)
{
    while ((x->siz)>((t+1)/2))
    x=merge(x->ls,x->rs);
}

int main()
{
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++)
    {
    b[i]=a[i];
    tre[i]=new node(b[i]);
    while (l && b[i]<b[q[l]])
    {
        tre[i]=merge(tre[i],tre[q[l]]);
        --l;
        pop(tre[i],i-q[l]);
        b[i]=tre[i]->val;
    }
    q[++l]=i;
    }
    now=1;
    l=1;
    while (now<=n)
    {
    b[now]=b[q[l]];
    if (now==q[l]) ++l;
    ++now;
    }
    for (int i=1;i<=n;i++) ans+=abs(a[i]-b[i]);
    memset(tre,0,sizeof(tre));
    l=0;
    for (int i=1;i<=n;i++)
    {
    b[i]=a[i];
    tre[i]=new node;
    while (l && b[i]>b[q[l]])
    {
        tre[i]=merge(tre[i],tre[q[l]]);
        --l;
        pop(tre[i],i-q[l]);
        b[i]=tre[i]->val;
    }
    q[++l]=i;
    }
    now=1;
    l=1;
    while (now<=n)
    {
    b[now]=b[q[l]];
    if (now==q[l]) ++l;
    ++now;
    }
    for (int i=1;i<=n;i++) tmp+=abs(a[i]-b[i]);
    printf("%d",min(ans,tmp));
    return 0;
}

[poj] 3666 Making the Grade

标签:修改   read   update   std   ace   val   name   merge   swa   

原文地址:http://www.cnblogs.com/mrha/p/7898477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!