zoukankan      html  css  js  c++  java
  • bzoj 1049 [HAOI2006]数字序列

    【bzoj1049】[HAOI2006]数字序列

    Description

    现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

    Input

    第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。

    Output

    第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

    Sample Input

    4
    5 2 3 5

    Sample Output

    1
    4

    HINT

    【数据范围】

    90%的数据n<=6000。

    100%的数据n<=35000。

    保证所有数列是随机的。

    这是证明:

     http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411

    题解:

        这道题目第一问是十分简单,但是我wrong了好久。

        第二问是变化幅度。

        对于第一问,因为a[i]-a[j]>=i-j

        所以(a[i]-i)-(a[j]-j)>=0

        所以可以设b[i]=a[i]-i

        所以只需要b[i]-b[j]>=0即可

        fz[i]表示当前这个点到i这个点为结尾的最大长度。

        g[i]表示1-i之间的答案。

        g[i]=min g[j]+w[j+1,i],转移条件是fz[j]+1=fz[i]

        有一个结论,在j-i中会有一个t,使得j--t都是b[j],t+1--i都是b[i],

        然后就是暴力即可。

     1 #include<cstring>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdio>
     6 #include<vector>
     7 
     8 #define ll long long
     9 #define N 350007
    10 using namespace std;
    11 inline int read()
    12 {
    13     int x=0,f=1;char ch=getchar();
    14     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
    15     while(ch<='9'&&ch>='0')
    16     {
    17         x=(x<<3)+(x<<1)+ch-'0';
    18         ch=getchar();
    19     }
    20     return x*f;
    21 }
    22 
    23 int n;
    24 ll g[N],s1[N],s2[N];
    25 int a[N],b[N],num,f[N],fz[N];
    26 vector<int>ve[N];
    27 
    28 void mid_find(int x,int i)
    29 {
    30     int l=1,r=num;
    31     while(l<r)
    32     {
    33         int mid=(l+r)>>1;
    34         if (f[mid]<=x) l=mid+1;
    35         else r=mid;
    36     }
    37     if (f[r]<=x) f[++num]=x,fz[i]=num;
    38     else f[r]=x,fz[i]=r;
    39 }
    40 void solve_lis()
    41 {
    42     for (int i=1;i<=n;i++)
    43     {
    44         b[i]=a[i]-i,g[i]=(1LL<<60);
    45         mid_find(b[i],i);
    46         //fz[i]=num;
    47         ve[fz[i]].push_back(i);
    48     }
    49     printf("%d
    ",n-fz[n]);
    50 }
    51 void solve()
    52 {
    53     b[0]=-(1<<30);ve[0].push_back(0);
    54     for (int i=1;i<=n;i++)
    55     {
    56         for (int j=0;j<ve[fz[i]-1].size();j++)
    57         {
    58             int pst=ve[fz[i]-1][j];
    59             if (b[pst]>b[i]) continue;
    60             for (int k=pst;k<=i;k++)
    61                 s1[k]=abs(b[k]-b[pst]),s2[k]=abs(b[k]-b[i]);
    62             for (int k=pst+1;k<=i;k++)
    63                 s1[k]+=s1[k-1],s2[k]+=s2[k-1];
    64             for (int k=pst;k<i;k++)
    65                 g[i]=min(g[i],g[pst]+s1[k]-s1[pst]+s2[i]-s2[k]);        
    66         }
    67     }
    68     printf("%lld",g[n]);
    69 }
    70 int main()
    71 {
    72     n=read();for (int i=1;i<=n;i++) a[i]=read();a[++n]=(1<<30);
    73     solve_lis();
    74     solve();
    75 }
  • 相关阅读:
    leetcode 122. Best Time to Buy and Sell Stock II
    leetcode 121. Best Time to Buy and Sell Stock
    python 集合(set)和字典(dictionary)的用法解析
    leetcode 53. Maximum Subarray
    leetcode 202. Happy Number
    leetcode 136.Single Number
    leetcode 703. Kth Largest Element in a Stream & c++ priority_queue & minHeap/maxHeap
    [leetcode]1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree
    正则表达式
    十种排序算法
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8029781.html
Copyright © 2011-2022 走看看