zoukankan      html  css  js  c++  java
  • 【poj3016】 K-Monotonic

    http://poj.org/problem?id=3016 (题目链接)

    题意

      给出一个数列,将一个数${a_i}$更改为${b_i}$的代价为${|a_i-b_i|}$。求将数列改为不递减的最小代价

    Solution

      话说我现在还没弄得明白→_→感觉论文的证明写的好搓。。

      左转题解:http://www.cnblogs.com/wenruo/p/5798801.html

    代码

    // poj3016
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 1<<30
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=2010;
    struct heap {int l,r,val,sz;}q[maxn];
    int num[maxn],rt[maxn],a[maxn],b[maxn],c[maxn];
    int cnt,n,K,in[maxn][maxn],de[maxn][maxn],f[maxn][maxn];
    
    int newq(int val) {
    	q[++cnt].val=val;
    	q[cnt].l=q[cnt].r=0;q[cnt].sz=1;
    	return cnt;
    }
    int merge(int x,int y) {
    	if (x==0 || y==0) return x+y;
    	if (q[x].val<q[y].val) swap(x,y);
    	q[x].r=merge(q[x].r,y);
    	swap(q[x].l,q[x].r);
    	q[x].sz=q[q[x].l].sz+q[q[x].r].sz+1;
    	return x;
    }
    int del(int x) {
    	int l=q[x].l,r=q[x].r;
    	return merge(l,r);
    }
    void cal(int *a,int u,int v,int *ans) {
    	int res=0,tot=0;cnt=0;
    	for (int i=u;i<=v;i++) {
    		rt[++tot]=newq(a[i]);
    		num[tot]=1;
    		while (tot>1 && q[rt[tot]].val<q[rt[tot-1]].val) {
    			tot--;
    			if (num[tot+1]&1) res+=q[rt[tot]].val-q[rt[tot+1]].val;
    			rt[tot]=merge(rt[tot],rt[tot+1]);
    			num[tot]+=num[tot+1];
    			while (q[rt[tot]].sz*2>num[tot]+1) rt[tot]=del(rt[tot]);
    		}
    		ans[i]=res;
    	}
    }
    int main() {
    	while (scanf("%d%d",&n,&K)!=EOF && n && K) {
    		for (int i=1;i<=n;i++) {
    			scanf("%d",&a[i]);
    			c[i]=-a[i]-i;
    			b[i]=a[i]-i;
    		}
    		for (int i=1;i<=n;i++) {
    			cal(c,i,n,de[i]);
    			cal(b,i,n,in[i]);
    		}
    		for (int i=1;i<=n;i++) f[0][i]=inf;
    		for (int i=1;i<=K;i++) {
    			f[i][0]=0;
    			for (int j=1;j<=n;j++) {
    				f[i][j]=inf;
    				for (int k=0;k<j;k++)
    					f[i][j]=min(f[i][j],f[i-1][k]+min(in[k+1][j],de[k+1][j]));
    			}
    		}
    		printf("%d
    ",f[K][n]);
    	}
        return 0;
    }
    
  • 相关阅读:
    kernel 于ioctl申请书
    顺时针打印矩阵
    HDU 1557 权利指数 国家压缩 暴力
    从混沌到有序--熵
    分层思想总结
    什么是分层架构模式
    分层设计
    分层设计思想
    软件的生长方式
    设计模式、SOLID原则:组件与联系
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6268698.html
Copyright © 2011-2022 走看看