题目描述
数轴上总计有 N N N( 1 ≤ N ≤ 1 0 5 1\le N\le 10^5 1≤N≤105)头奶牛。第 i i i 头奶牛的位置为 x i x_i xi( 0 ≤ x i ≤ 1 0 9 0 \leq x_i \leq 10^9 0≤xi≤109),而第 i i i 头奶牛的重量为 y i y_i yi( 1 ≤ y i ≤ 1 0 4 1 \leq y_i \leq 10^4 1≤yi≤104)。
根据 Farmer John 的信号,某些奶牛会组成对,使得
-
每一对包含位置相差不超过 K K K 的两头不同的奶牛 a a a 和 b b b( 1 ≤ K ≤ 1 0 9 1\le K\le 10^9 1≤K≤109);也就是说, ∣ x a − x b ∣ ≤ K |x_a-x_b|\le K ∣xa−xb∣≤K。
-
每一头奶牛要么包含在恰好一对中,要么不属于任何一对。
-
配对是极大的;也就是说,没有两头未配对的奶牛可以组成对。
你需要求出未配对的奶牛的重量之和的可能的范围。具体地说,
-
如果 T = 1 T=1 T=1,计算未配对的奶牛的最小重量和。
-
如果 T = 2 T=2 T=2,计算未配对的奶牛的最大重量和。
题解
T = 1 T=1 T=1 和 T = 2 T=2 T=2 本质上是一样的,把 y i y_i yi 全部取其相反数即可相互转换。下面只考虑 T = 1 T=1 T=1 的情况。
由于配对是极大的,所以每个未配对的奶牛之间距离大于 k k k,并且剩下的奶牛要能全部匹配。
显然让相邻的两头奶牛匹配是最优的。
考虑 d p dp dp 求解。
设 f i , j f_{i,j} fi,j 表示处理了前 i i i 个奶牛,未配对的奶牛数是奇数还是偶数( j ∈ { 0 , 1 } j\in\{0,1\} j∈{0,1})。
对于 f i , j f_{i,j} fi,j,若 j = i % 2 j=i\%2 j=i%2,表示配对的奶牛数是偶数,否则为奇数。
初始状态 f 0 , 0 = 0 f_{0,0}=0 f0,0=0
记 n o w now now 为第 i i i 头奶牛前面到 i i i 距离大于 k k k 的最大的奶牛位置。
令 j = i % 2 j=i\%2 j=i%2。
下面分类讨论
- i i i 前面选择了偶数头奶牛,并且不选 i i i。显然 i i i 前面选的奶牛都是已配对的。因为 i i i 未配对,所以位置大于 n o w now now 小于 i i i的奶牛都必须配对。转移为 f i , j = min ( f i , j , f n o w , 1 − j + y i ) f_{i,j}=\min(f_{i,j},f_{now,1-j}+y_i) fi,j=min(fi,j,fnow,1−j+yi)
- i i i 前面选择了偶数头奶牛,并且选 i i i。这时第 i i i 头奶牛需要与后面的奶牛配对,因此转移条件为 x i + 1 − x i ≤ k x_{i+1}-x_i\le k xi+1−xi≤k。前面 i i i 头奶牛匹配了奇数头奶牛,转移方程为 f i , 1 − j = min ( f i , 1 − j , f i − 1 , 1 − j ) f_{i,1-j}=\min(f_{i,1-j},f_{i-1,1-j}) fi,1−j=min(fi,1−j,fi−1,1−j)
- i i i 前面选择了奇数头奶牛,并且选 i i i。这时第 i − 1 i-1 i−1 头奶牛是未匹配的,它需要与第 i i i 头奶牛匹配。转移条件为 x i − x i − 1 ≤ k x_i-x_{i-1}\le k xi−xi−1≤k。转移方程为 f i , 1 − j = min ( f i , 1 − j , f i − 1 , j ) f_{i,1-j}=\min(f_{i,1-j},f_{i-1,j}) fi,1−j=min(fi,1−j,fi−1,j)
- i i i 前面选择了奇数头奶牛,并且不选 i i i。这时第 i − 1 i-1 i−1 头奶牛是未匹配的,它需要与第 i + 1 i+1 i+1 头奶牛匹配。转移条件为 x i + 1 − x i − 1 ≤ k x_{i+1}-x_{i-1}\le k xi+1−xi−1≤k。转移方程为 f i , 1 − j = min ( f i , 1 − j , f n o w , j + y i ) f_{i,1-j}=\min(f_{i,1-j},f_{now,j}+y_i) fi,1−j=min(fi,1−j,fnow,j+yi)
里面的状态要仔细品味。
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1,INF=1e9+1;
int t,n,k,x[N],y[N],fl=1,now;
int f[N][2];
int main()
{
scanf("%d%d%d",&t,&n,&k);
if(t==2) fl=-1;
for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]),y[i]*=fl;
x[0]=-INF,x[n+1]=INF;
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++){
while(x[i]-x[now+1]>k) now++;
int j=i&1;
f[i][j]=min(f[i][j],f[now][j^1]+y[i]);
if(x[i+1]-x[i]<=k) f[i][j^1]=min(f[i][j^1],f[i-1][j^1]);
if(x[i]-x[i-1]<=k) f[i][j]=min(f[i][j],f[i-1][j]);
if(x[i+1]-x[i-1]<=k) f[i][j^1]=min(f[i][j^1],f[now][j]+y[i]);
}
printf("%d",f[n][n&1]*fl);
}