思维,序列和

Contest (nefu.edu.cn)

Problem:G
Time Limit:2000ms
Memory Limit:65535K

Description

Catly有k个序列,每个序列有ni个元素,Catly想知道是否在k个序列中有两个序列,p和q,只要删除p中一个元素和q中一个元素,能使得q中元素和等于q中元素和

Input

第一行一个k(2<=k<=2e5) 代表有k个序列
接下来有2*k行,一行为ni(1<=ni<=2e5)代表第i个序列有多少个元素,数据保证k<=n1+...+nk<=2e5
下面一行有ni个数字aj(-10000<=aj<=10000)代表第i个序列中的元素

Output

如果有输出YES,并输出是哪两个序列x,y(x<y,x最小),若有多组解输出序列号y+x最小的一对,否则输出NO
2023.9.24 _Yuu修改:若有多解请输出以x+y为第一依据升序,以x为第二依据降序的第一个

Sample Input

2
5
2 3 1 3 2
6
1 1 2 2 2 1

Sample Output

YES
1 2
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
int n;
int arr[N];
unordered_map<int, pair<int, int>>mp;

int main() {
	int k, sum = 0;
	scanf("%d", &k);
	for (int i = 1; i <= k; i++) {
		scanf("%d", &n);
		sum = 0;
		for (int j = 1; j <= n; j++) {
			scanf("%d", &arr[j]);
			sum += arr[j];
		}
		for (int j = 1; j <= n; j++) {
			if (!mp[sum - arr[j]].first)mp[sum - arr[j]].first = i;
			else if (!mp[sum - arr[j]].second && mp[sum - arr[j]].first != i)
				mp[sum - arr[j]].second = i;
		}
	}
	int x=k+1, y=k+1;
	for (unordered_map<int, pair<int, int>>::iterator i = mp.begin(); i != mp.end();i++) {
		//cout << "SSSSSSSSSS" << endl;
		if (i->second.second && i->second.first) {
			int a = i->second.first;
			int b = i->second.second;
			if (x + y > a + b || (x + y == a + b && b < y)) {
				x = min(a, b);
				y = max(a, b);
			}
		}
	}
	if (x != k + 1)
		printf("YES\n%d %d\n", x, y);
	else
		printf("NO\n");
	return 0;
}

posted @ 2023-09-28 20:12  Landnig_on_Mars  阅读(5)  评论(0编辑  收藏  举报  来源