其他分享
首页 > 其他分享> > 0707灵动集训

0707灵动集训

作者:互联网

团结力量大

Description

为了让大家体会团结力量大,高老师决定带领大家做一个活动,她把同学们分成了 n 个小组,每组 m 个同学,每个同学手里有一个自然数。

她让每组内的同学按如下方式合并成团:

高老师的学生都非常聪明,现在她想知道,每个组最高合并出的分数是多少?答案保证在 \(2^{63}-1\) 以内。

Format

Input

第一行输入两个整数 \(n,m(1\le n\le 500000, 1\le m \le 20)\)

第二行开始,每行输入 \(m\) 个整数,表示一个组中每位同学的分数\((0\sim 7)\)

Output

n 行,每行一个整数,表示对应的组可以合并出的最高分。

Editorial

this problem seems like "合并果子" in which it can be proved that choosing the smallest value always gives the maximum answer.

Actually,this problem has the same editorial with it : always select the smallest.

Using priority queue it's quite a well solution,but in this question,Time complexity should to be close to \(O(n)\).therefore,we can use bucket sort to replace std::sort,and optimizing priority queue with normal queues.

we assume that queue q has all the result of the merge. obviously,the elements in q are monotonically increasing. therefore,the smallest elements is between the sorted array \(a\) and the front of the queue \(q\).

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
queue<ll>x,y;
//get the minimum between two queues 
ll Get() {
	int x1 = -1;
	if(x.size())
		x1 = x.front();
	int y1 = -1;
	if(y.size())
		y1 = y.front();
	if(x1==-1) {
		y.pop();
		return y1;
	}
	if(y1==-1) {
		x.pop();
		return x1;
	}
	if(x1<y1) {
		x.pop();
		return x1;
	} else {
		y.pop();
		return y1;
	}
}

int main() {
	int n,m;
	cin >> n >> m;
	while(n--) {
		// clear
		while(x.size())
			x.pop();
		while(y	.size())
			y.pop();
			
		vector<ll>a(m);
		for(auto &i:a)
			cin >> i;
		if(m==1) {
			cout << a[0] << endl;
			return 0;
		}
		sort(a.begin(),a.end());
		for(auto &i:a)
			x.push(i);
		while(x.size()!=0||y.size()!=1) {
			ll n1 = Get(), n2 = Get();
			y.push(n1*n2+1);
		}
		cout << y.front() << endl;
	}
}

标签:分数,le,pop,queue,灵动,y1,x1,0707,集训
来源: https://www.cnblogs.com/zhaohanzheng/p/16457523.html