一类有关序列的技巧问题



问题一:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=601&pid=1005

我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。 请输出最少需要修改多少个元素。


选取最长的符合要求的序列,然后把其他值改变即可。如何找到符合要求的序列?因为要递增,所以每个数和它自身所在的位置有关,也就是自身占据了位置的权重,所以每个数减去对应的位置的权即a[i]-i,还原出主要矛盾,然后取一条非降LIS即可

    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        scanf("%d",&n);
        int LIS;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]-=i;
        for(int i=1;i<=n;i++) dp[i]= inf;
        for(int i=1;i<=n;i++) *upper_bound(dp+1,dp+n+1,a[i])=a[i];
        for(int i=1;i<=n;i++) if(dp[i]!=inf) LIS=i;
        printf("Case #%d:\n%d\n",cas,n-LIS);
    }

问题二:http://codeforces.com/contest/549/problem/G

已知一个序列,问是否可以经过相邻两个数的调换得到非降的序列,调换的代价是AiAj换成AjAi后,Aj增大1,Ai减少了1.

思路:仍然可以发现每个数对应不同位置自身带有不同的权(潜在价值),所以每个数a[i]+i后,是他们的总价值,sort后他们若严格递增再减去潜在价值后的序列一定非降,然后输出答案,否则无法调换完成。

int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i],a[i]+=i;
    sort(a,a+n);
    for(int i=0;i<n;i++) a[i]-=i;
    for(int i=0;i<n-1;i++) if(a[i]>a[i+1]){
        puts(":(");
        exit(0);
    }
    for(int i=0;i<n;i++) printf("%d ",a[i]);
}


问题三:(忘记题源了)

x轴有n个点,分别对应坐标xi,问最少要把点累计移动多长的距离才能使他们成为间隔L的整齐排列。

思路:显然每个点对应相应的潜在价值,每个点的坐标Xi减L*i,即还原了主要矛盾,现在把这些新的点均移到某个同一点即可。

显然移到他们的中位点产生的累计移动距离最小。


你可能感兴趣的:(一类有关序列的技巧问题)