zoukankan      html  css  js  c++  java
  • [poj] 3666 Making the Grade

    原题

    左偏树裸题(也可以用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;
    }
    
  • 相关阅读:
    Excel的小游戏总结
    借助“URLScan”工具隐藏header头服务器信息
    WinCe设备连接Win10系统
    WinForm 通过HttpWebRequest实现大文件上传
    Sql 动态行转列 pivot
    C# 调用LAKALA接口获取静态二维码数据
    蜗牛星际黑群晖硬盘休眠的设置
    GIT Windows服务端搭建笔记
    C#通过socket判断FTP服务器是否通畅并判断用户名密码是否正确
    C#获取MAC地址
  • 原文地址:https://www.cnblogs.com/mrha/p/7898477.html
Copyright © 2011-2022 走看看