• NKOJ3485 【2015多校联训4】数据


    问题描述

    Mr_H 出了一道信息学竞赛题,就是给 n 个数排序。输入格式是这样的:
    试题有若干组数据。每组数据的第一个是一个整数 n,表示总共有 n 个数待排序;接下来 n 个整数,分别表示这n 个待排序的数。
    例如:3 4 2 –1 4 1 2 3 4,就表示有两组数据。第一组有3 个数(4,2,-1),第二组有4个数(1,2,3,4)。可是现在Mr_H 做的输入数据出了一些问题。
    例如:2 1 9 3 2 按理说第一组数据有2 个数(1,9),第二组数据有3 个数,可是“3”后面并没有出现三个数,只出现了一个数“2”而已!
    现在 Mr_H 需要对数据进行修改,改动中“一步”的含义是对文件中的某一个数+1 或-1,写个
    程序,计算最少需要多少步才能将数据改得合法。

    输入格式

    第一行一个整数m,表示Mr_H 做的输入数据包含的整数个数。第二行包含m 个整数a[i],每个整数的绝对值不超过10000。

    输出格式

    一个整数,表示把数据修改为合法的情况下,最少需要多少步。

    样例输入

    【样例输入1】
    4
    1 9 3 2

    【样例输入2】
    10
    4 4 3 5 0 -4 -2 -1 3 5

    样例输出

    【样例输出1】
    2

    【样例输出2】
    3

    提示

    【数据范围】
    对于 20%的数据,m<=10, |a[i]|<=5;
    对于60%的数据,m<=5000, |a[i]|<=10000
    对于100%的数据,m<=100000, |a[i]|<=10000


    来源  by YZ

    【题解】

    dp(i)=min{dp(j)+|num(j+1)-(i-j-1)|}

    num(j+1)-(i-j-1)>=0 ,即i<num(j+1)+j+1时 dp(i)=min{dp(j)+num(j+1)+j+1}-i
    num(j+1)-(i-j-1)<0,即i>num(j+1)+j+1时 dp(i)=min{dp(j)-num(j+1)-j-1}-i
    我们不难用一颗权值线段树去维护,线段树的下标表示num(j+1)+j+1,值
    dp(j)-num(j+1)-j-1  / dp(j)+num(j+1)+j+1的最小值。

    查询dp(j)+num(j+1)+j+1线段树的i....max和

    dp(j)-num(j+1)-j-1线段树的1...i-1即可

    对拍无误

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #define max(a, b) ((a) > (b) ? (a) : (b))
     6 #define min(a, b) ((a) < (b) ? (a) : (b))
     7 
     8 inline void read(int &x)
     9 {
    10     x = 0;char ch = getchar(), c = ch;
    11     while(ch < '0' || ch > '9')c = ch, ch = getchar();
    12     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
    13     if(c == '-')x = -x; 
    14 }
    15 
    16 const int MAXM = 200000 + 10;
    17 const int MAXNUM = 1000000;
    18 const int PIAN = 11000;
    19 const int INF = 0x3f3f3f3f;
    20 
    21 int m,dp[MAXM],num[MAXM];
    22 
    23 int mi[2][MAXNUM + 10], sum;
    24 /*
    25 f(i)=min{f(j)+|A(j+1)-(i-j-1)|}
    26 0: num(j+1)-(i-j-1)>0 -> i<num(j+1)+j+1  f(i)=min{f(j) + num(j+1) - (-j-1)} - i
    27 1: num(j+1)-(i-j-1)<=0 -> i>num(j+1)+j+1 f(i)=min{f(j) + (-j-1) - num(j+1)} + i
    28 */
    29 
    30 void modify(int a, int p, int k, int o = 1, int l = 1, int r = sum + PIAN)
    31 {
    32     if(l == r && l == p)
    33     {
    34         mi[a][o] = min(k, mi[a][o]);
    35         return;
    36     }
    37     int mid = (l + r) >> 1;
    38     if(mid >= p)modify(a, p, k, o << 1, l, mid);
    39     else modify(a, p, k, o << 1 | 1, mid + 1, r);
    40     mi[a][o] = min(mi[a][o], min(mi[a][o << 1], mi[a][o << 1 | 1]));
    41 }
    42 
    43 int ask(int a, int ll, int rr, int o = 1, int l = 1, int r = sum + PIAN)
    44 {
    45     if(ll <= l && rr >= r) return mi[a][o];
    46     int mid = (l + r) >> 1;
    47     int ans = INF;
    48     if(mid >= ll)ans = min(ans, ask(a, ll, rr, o << 1, l, mid));
    49     if(mid < rr)ans = min(ans, ask(a, ll, rr, o << 1 | 1, mid + 1, r));
    50     return ans;
    51 }
    52 
    53 int main()
    54 {
    55     read(m);
    56     for(register int i = 1;i <= m;++ i)
    57         read(num[i]), sum = max(sum, num[i] + i + 1 + PIAN);
    58     memset(dp, 0x3f, sizeof(dp));
    59     memset(mi, 0x3f, sizeof(mi));
    60     dp[0] = 0;
    61     modify(0,num[1] + 1 + PIAN, num[1] + 1);
    62     modify(1,num[1] + 1 + PIAN, -num[1] - 1); 
    63     for(register int i = 1;i <= m;++ i)
    64     {
    65         int k1 = ask(0, min(sum, i) + PIAN, sum + PIAN) - i;
    66         int k2 = ask(1, 1, max(1, i - 1) + PIAN) + i;
    67         if(k2 <= i - INF)k2 = INF;
    68         dp[i] = min(dp[i], min(k1, k2));
    69         modify(0, num[i + 1] + i + 1 + PIAN, dp[i] + num[i + 1] + i + 1);
    70         modify(1, num[i + 1] + i + 1 + PIAN, dp[i] - num[i + 1] - i - 1);
    71     }
    72     printf("%d", dp[m]);
    73     return 0;
    74 }
    my
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<queue>
     7 using namespace std;
     8 const int inf=0x3f3f3f3f;
     9 template <typename T>
    10 inline void _read(T& x){
    11     char t=getchar();bool sign=true;
    12     while(t<'0'||t>'9')
    13     {if(t=='-')sign=false;t=getchar();}
    14     for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    15     if(!sign)x=-x;
    16 }
    17 int n;
    18 int a[200005];
    19 int f[200005];
    20 int mark[200005];
    21 vector<int> v[200005];
    22 struct node{
    23     int x,y;
    24     node(){}
    25     node(int g,int h){x=g;y=h;}
    26     bool operator < (const node p)const {
    27         return y>p.y;
    28     }
    29 };
    30 priority_queue<node>q1;
    31 priority_queue<node>q2;
    32 void dajia(){
    33     int i,j,k;
    34     for(i=1;i<=n;i++){
    35         f[i]=inf;
    36         for(k=i-1;k>=0;k--){
    37             f[i]=min(f[i],f[k]+abs(a[k+1]-(i-k-1)));
    38         }
    39     }
    40 }
    41 void daqunjia(){
    42     int i,j,k,temp;
    43     q1.push(node(0,a[1]+1));
    44     for(i=1;i<=n;i++){
    45         temp=-1;
    46         for(j=0;j<v[i].size();j++){
    47             mark[v[i][j]]=2;
    48             if(v[i][j]<i)q2.push(node(v[i][j],f[v[i][j]]-a[v[i][j]+1]-v[i][j]-1));
    49         }
    50         while(q1.size()&&mark[q1.top().x]==2){
    51             q1.pop();
    52         }
    53         if(q1.size()){
    54             temp=q1.top().y-i;
    55         }
    56         if(q2.size()){
    57             if(temp==-1)temp=q2.top().y+i;
    58             else temp=min(temp,q2.top().y+i);
    59         }
    60         f[i]=temp;
    61         if(mark[i]==2){
    62             q2.push(node(i,f[i]-a[i+1]-i-1));
    63         }
    64         else q1.push(node(i,f[i]+a[i+1]+i+1));
    65     } 
    66 }
    67 int main(){
    68     freopen("data.txt", "r", stdin); 
    69     int i,j,k,temp;
    70     cin>>n;
    71     for(i=1;i<=n;i++){
    72         _read(a[i]);
    73         if(a[i]+i<=1)v[1].push_back(i-1);
    74         v[a[i]+i].push_back(i-1);
    75     }
    76     if(n<=5000)dajia();
    77     else daqunjia();
    78     cout<<f[n];
    79 } 
    std
     1 #include <bits/stdc++.h>
     2 
     3 const int MAXN = 100000;
     4 const int MAXNUM = 10000;
     5 
     6 int main()
     7 {
     8     srand(time(NULL));
     9     int n = rand() % MAXN + 1;
    10     printf("%d
    ", n);
    11     for(register int i = 1;i <= n;++ i)
    12     {
    13         int b = rand()%2;
    14         if(b) printf("%d ",-rand()%MAXNUM+1);
    15         else printf("%d ", rand()%MAXNUM+1);
    16     }
    17     return 0;
    18 }
    rand
     
     
  • 相关阅读:
    echarts各个配置项详细说明总结
    享元模式
    观察者模式
    策略模式
    桥接模式
    适配器模式
    建造者模式
    原型模式
    单例模式
    Java8新特性——集合底层源码实现的改变
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7549853.html
Copyright © 2020-2023  润新知