【LGR-075 洛谷 8 月月赛 II Div.2】T2 排列 【数学】

题目描述
pigstd 有一堆数,他想在这么多数中选出若干个数排成一列,记为 x 1 ​ , x 2 , ⋯ , x p x_1​ ,x_2 ,⋯,x_p x1,x2,,xp(p 为数的个数)。这一列数合法当且仅当满足以下条件:

  • p ≥ 2 p≥2 p2
  • y i = x i + 1 − x i y_i =x_i+1−x_i yi=xi+1xi
    ​(特别的, y p ​ = x 1 ​ − x p y_p​ =x_1​ −x_p yp=x1xp ),如果把 y 1 y_1 y1 y p y_p yp y 1 , y 2 , ⋯ , y p y_1 ,y_2,⋯,y_p y1,y2,,yp的顺序排成一圈,那么每两个相邻的数互为相反数且绝对值都为 k k k

p i g s t d pigstd pigstd 想知道,在所有合法的数列中,所有在这个数列中的数之和最大是多少。


输入格式
第一行两个整数 n , k n,k n,k

接下来 n 行,每行两个整数 a i , b i a_i,b_i ai,bi,表示 p i g s t d pigstd pigstd b i b_i bi a i a_i ai
不保证 a i a_i ai互不相同,若有 a i ​ a i​ ai

相同则累加其个数计算。

输出格式
一行一个整数,表示在每一种排列中,所有在这个排列中的数的最大的和。

若没有合法的排列,则只输出 N O NO NO


输入输出样例

输入 #1复制
4 3
1 5
2 4
3 3
0 2

输出 #1复制
6


说明/提示
【样例 1 说明】
p i g s t d pigstd pigstd 的排列为: 0 , 3 , 0 , 3 0,3,0,3 0,3,0,3 3 , 0 , 3 , 0 3,0,3,0 3,0,3,0 时,总和最大,为 6 6 6

【数据规模与约定】
对于 100% 的数据, 1 ≤ n ≤ 1 0 6 , 0 ≤ k , a i ≤ 1 0 6 , 1 ≤ b i ≤ 1 0 6 1≤n≤10^6 ,0≤k,a_i≤10^6,1≤b_i≤10^6 1n1060k,ai1061bi106

本题采用捆绑测试。

  • S u b t a s k Subtask Subtask 1 ( 5 p o i n t s ) (5 points) 5points:保证无合法的数列;
  • S u b t a s k Subtask Subtask 2 ( 15 p o i n t s ) (15 points) 15points k = 0 k = 0 k=0
  • S u b t a s k Subtask Subtask 3 ( 5 p o i n t s ) (5 points) 5points n = 1 n = 1 n=1
  • S u b t a s k Subtask Subtask 4 ( 5 p o i n t s ) (5 points) 5points n = 2 n = 2 n=2
  • S u b t a s k Subtask Subtask 5 ( 30 p o i n t s ) (30 points) 30points n , k , a i , b i ≤ 1 0 3 n,k,a_i,b_i ≤10^3 n,k,ai,bi103
  • S u b t a s k Subtask Subtask 6 ( 40 p o i n t s ) (40 points) 40points:无特殊限制。

解题思路
由我一系列的推导发现:你只能在这个序列中选两种不同的数。。。
SO,这道题就可以用模拟水了。

简单的,暴力的,枚举 i i i,若i与i+k都存在,即组成一种方案,然后他们的总和为 ( i + i + k ) ∗ m i n ( a [ i ] , a [ i + k ] ) (i+i+k)*min(a[i],a[i+k]) (i+i+k)min(a[i],a[i+k])。。。

PS:特判 k = = 1 k==1 k==1 的情况 (^ _ ^)


代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
long long n,k,x,y,xx,ans,maxn,a[1000100];
bool flag=0;
int main(){
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&x,&y);
		maxn=max(maxn,x);
		a[x]+=y;
	}
	for(int i=0;i<=maxn-k;i++)
	{
		if(a[i]&&a[i+k])
		{
			if(k!=0) 
			{
				flag=1;
				xx=(i+i+k)*min(a[i],a[i+k]);
				ans=max(ans,xx);
			}
			else if(a[i]>1)
			{
				flag=1;
				xx=i*a[i];
				ans=max(ans,xx);
			}
		}
	}
	if(flag==1)
		printf("%lld",ans);
	else
		printf("NO");
}

你可能感兴趣的:(数学,洛古)