NKOJ3485 2015多校联训4数据
Posted 嘒彼小星
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
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 }
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", 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 }
以上是关于NKOJ3485 2015多校联训4数据的主要内容,如果未能解决你的问题,请参考以下文章
Contest1893 - 2019年6月多校联训b层测试1