2019 GDUT Spring Team_up Training IV(Div.2)(优先队列,暴力,思维,玄学)(2019/4/16)

A. Coffee Break

time limit per test 2.0 s
memory limit per test 256 MB
input standard input
output standard output
Recently Monocarp got a job. His working day lasts exactly m minutes. During work, Monocarp wants to drink coffee at certain moments: there are n minutes a1,a2,…,an, when he is able and willing to take a coffee break (for the sake of simplicity let’s consider that each coffee break lasts exactly one minute).
However, Monocarp’s boss doesn’t like when Monocarp takes his coffee breaks too often. So for the given coffee break that is going to be on minute ai, Monocarp must choose the day in which he will drink coffee during the said minute, so that every day at least d minutes pass between any two coffee breaks. Monocarp also wants to take these n coffee breaks in a minimum possible number of working days (he doesn’t count days when he is not at work, and he doesn’t take coffee breaks on such days). Take into account that more than d minutes pass between the end of any working day and the start of the following working day.
For each of the n given minutes determine the day, during which Monocarp should take a coffee break in this minute. You have to minimize the number of days spent.

Input

The first line contains three integers n, m, d (1≤n≤2⋅105,n≤m≤109,1≤d≤m) — the number of coffee breaks Monocarp wants to have, the length of each working day, and the minimum number of minutes between any two consecutive coffee breaks.
The second line contains n distinct integers a1,a2,…,an (1≤ai≤m), where ai is some minute when Monocarp wants to have a coffee break.

Output

In the first line, write the minimum number of days required to make a coffee break in each of the n given minutes.
In the second line, print n space separated integers. The i-th of integers should be the index of the day during which Monocarp should have a coffee break at minute ai. Days are numbered from 1. If there are multiple optimal solutions, you may print any of them.

Examples
input

4 5 3
3 5 1 2

output

3
3 1 1 2

input

10 10 1
10 5 7 4 6 3 2 1 9 8

output

2
2 1 1 2 2 1 2 1 1 2

Note

In the first example, Monocarp can take two coffee breaks during the first day (during minutes 1 and 5, 3 minutes will pass between these breaks). One break during the second day (at minute 2), and one break during the third day (at minute 3).

In the second example, Monocarp can determine the day of the break as follows: if the minute when he wants to take a break is odd, then this break is on the first day, if it is even, then this break is on the second day.

题目大意:

在n个时间段中,你能喝咖啡,但每天要喝一次咖啡后,就要隔d+1分钟才能再喝,问能最少安排多少天把这些时间段喝一次咖啡。

题目思路:

先排序,再建一个优先队列,结构体天数,每次对比优先队列的第一个,如果可以则放入队列中(天数不加),不可以也放入队列中(天数加)。
然后按序号输出即可。
代码:

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=2e5+5;
struct node{
	int num,index,cnt;
	node(int _num=0,int _index=0,int _cnt=0):num(_num),index(_index),cnt(_cnt){}
	bool friend operator < (node a,node b){
		return a.num<b.num;
	}
}a[maxn];
bool cmp(node a,node b){
	return a.num<b.num;
}
int main(){
	int n,m,d;
	int b[maxn];
	queue <node> q;
	cin>>n>>m>>d;
	int x;
	for(int i=0;i<n;i++){
		scanf("%d",&a[i].num);
		a[i].index=i;
	}
	sort(a,a+n,cmp);
	int cnt=1;
	int i,j;
	q.push(node(a[0].num,a[0].index,1));
	for(i=1;i<n;i++){
		if(a[i].num>q.front().num+d){
			b[q.front().index]=q.front().cnt;
			q.push(node(a[i].num,a[i].index,q.front().cnt));
			q.pop();
		}else{
			q.push(node(a[i].num,a[i].index,++cnt));
		}
	}
	while(!q.empty()){
		b[q.front().index]=q.front().cnt;
		q.pop();
	}
	cout<<cnt<<endl;
	for(i=0;i<n;i++){
		printf("%d%c",b[i],i==n-1?'\n':' ');
	}
	return 0;
}

D. Masquerade strikes back

time limit per test 2.0 s
memory limit per test 512 MB
input standard input
output standard output
Quite often the jury of Saratov SU use the problem “Masquerade” in different practice sessions before the contest. This problem is quite easy — all you need is to print the product of two integers which were read from the input stream.
As usual, the jury had prepared this problem once again. The jury had n testcases, the i-th testcase was a pair of positive integers ai and bi, both integers didn’t exceed 107. All testcases were pairwise distinct.
Unfortunately, something went wrong. Due to hardware issues all testcases have disappeared. All that the jury were able to restore are the number of testcases n and the answers to these testcases, i. e. a sequence of n numbers c1,c2,…,cn, such that ai⋅bi=ci.
The jury ask you to help them. Can you provide any possible testset? Remember that all testcases were distinct and all numbers in each testcase were positive integers and didn’t exceed 107.

Input

First line contains one insteger n (1≤n≤2⋅105) — the number of lost testcases.
Second line contains n space-separated integers c1,c2,…,cn (1≤ci≤107) — the answers to the testcases.

Output

If there is no such testset, print NO.

Otherwise, print YES in first line. Then print n more lines, the i-th of them should contain two space separated positive integers ai and bi not exceeding 107. All pairs (ai,bi) must be distinct, and, for each i∈[1,n], the condition ai⋅bi=ci must be met.

Examples
input

4
1 3 3 7

output

YES
1 1
1 3
3 1
1 7

input

5
3 1 3 3 7

output

NO

input

6
9 10 9 10 9 10

output

YES
1 9
1 10
3 3
5 2
9 1
2 5

Note

In the first example one of the possible testsets is (a1=1, b1=1), (a2=1, b2=3), (a3=3, b3=1), (a4=1, b4=7).
In the second example a testset consisting of distinct tests doesn’t exist.

题目大意:

给你n个数,然后输出每个数的因数和这个数/因数的数,可以反过来,但是不可以重复。可以实现输出YES,和每个数分解成的两个数,不可以实现输出NO。

题目思路:

设置个vis数组,表示每个数的访问次数,1次即这个数和1,2次即1和这个数,如此分解,每次向下到vis+1,数据不大,暴力即可过。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=2e5+5;
int n,a[maxn];
pair<int,int> ans[maxn];
int vis[10000005]={0};
int top=0;
int main(){
	cin>>n;
	int i,j;
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<n;i++){
		vis[a[i]]++;
		//printf("%d %d %d\n",i,a[i],vis[a[i]]);
		int lim=sqrt(a[i]);
		int cnt=0;
		for(j=1;j<=lim;j++){
			if(a[i]%j==0){
				cnt++;
				if(cnt==vis[a[i]]){
					ans[top++]=make_pair(j,a[i]/j);
					break;
				}
				if(j*j!=a[i])cnt++;
				if(cnt==vis[a[i]]){
					ans[top++]=make_pair(a[i]/j,j);
					break;
				}
			}
		}
		if(cnt<vis[a[i]]){
			puts("NO");
			return 0;
		}
	}
	puts("YES");
	for(i=0;i<top;i++){
		printf("%d %d\n",ans[i].first,ans[i].second);
	}
}

G. Tree Reconstruction

time limit per test 1.0 s
memory limit per test 256 MB
input standard input
output standard output
Monocarp has drawn a tree (an undirected connected acyclic graph) and then has given each vertex an index. All indices are distinct numbers from 1 to n. For every edge e of this tree, Monocarp has written two numbers: the maximum indices of the vertices of the two components formed if the edge e (and only this edge) is erased from the tree.
Monocarp has given you a list of n−1 pairs of numbers. He wants you to provide an example of a tree that will produce the said list if this tree exists. If such tree does not exist, say so.

Input

The first line contains one integer n (2≤n≤1000) — the number of vertices in the tree.
Each of the next n−1 lines contains two integers ai and bi each (1≤ai<bi≤n) — the maximal indices of vertices in the components formed if the i-th edge is removed.

Output

If there is no such tree that can produce the given list of pairs, print “NO” (without quotes).
Otherwise print “YES” (without quotes) in the first line and the edges of the tree in the next n−1 lines. Each of the last n−1 lines should contain two integers xi and yi (1≤xi,yi≤n) — vertices connected by an edge.
Note: The numeration of edges doesn’t matter for this task. Your solution will be considered correct if your tree produces the same pairs as given in the input file (possibly reordered). That means that you can print the edges of the tree you reconstructed in any order.

Examples
input

4
3 4
1 4
3 4

output

YES
1 3
3 2
2 4

input

3
1 3
1 3

output

NO

input

3
1 2
2 3

output

NO

Note

Possible tree from the first example. Dotted lines show edges you need to remove to get appropriate pairs.

题目大意:

不成环的树,给你将每条边去掉后两部分的最大值(共n-1个)
输出这个树边的连接。

题目思路:

首先给你两个最大值一定会有一个是最大值n,其次,每个数出现的次数不能超过它本身。然后我们就考虑怎么建图了,我们可以想想,如果一个点出现两次,那么它到最大值有两条边的距离且这个点是最边上的点,如果一个点没出现,那它一定不在最边上,且最边上的点一定比它大。所以我们可以查找没出现过的,往比它大的出现过的连接,这样就是解了。

n 出现次数
2 0
3 0
4 3
那么我们就可以4-2-3-最大值
然后出现一次的本身和最大值相连i-最大值
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e3+5;
int main(){
	vector <int> edge[maxn];
	int n;
	cin>>n;
	int t[maxn]={0},vis[maxn]={0},one[maxn]={0};
	int flag=0;
	int x,y,i,j;
	for(i=1;i<n;i++){
		scanf("%d %d",&x,&y);
		t[min(x,y)]++;
		if(max(x,y)!=n) flag=1;
	}
	for(i=1;i<=n;i++){
		if(t[i]>i) flag=1;
		if(t[i]==1) one[i]=1;
		edge[i].push_back(i);
	}
	if(flag){
		puts("NO");
		return 0;
	}
	for(i=1;i<n;i++){
		if(t[i]==0){
			for(j=i+1;j<n;j++){
				if(t[j]>1){
					edge[j].push_back(i);
					t[j]--;
					break;
				}
			}
			if(j==n){
				puts("NO");
				return 0;
			}
		}
	}

	/*for(i=1;i<n;i++){
		if(edge[i].size()>0){
			edge[n].push_back(edge[i][edge[i].size()-1]);
		}
	}*/
	puts("YES");
	for(i=1;i<=n;i++){
		for(j=0;j<edge[i].size()-1;j++){
			printf("%d %d\n",edge[i][j],edge[i][j+1]);
			if(j==edge[i].size()-2){
				printf("%d %d\n",edge[i][j+1],n);
			}
		}
	}
	for(i=0;i<n;i++){
		if(one[i]) printf("%d %d\n",i,n);
	}
	return 0;
}

K. Medians and Partition

time limit per test 1.0 s
memory limit per test 256 MB
input standard input
output standard output
Let median of some array be the number which would stand in the middle of this array if it was sorted beforehand. If the array has even length let median be smallest of of two middle elements. For example, median of the array [10,3,2,3,2] is 3 (i.e. [2,2,3–,3,10]). Median of the array [1,5,8,1] is 1 (i.e. [1,1–,5,8]).
Let array be m-good if its median is greater or equal than m.
Let the partition of array [a1,a2,…,an] be a set of subarrays {b1,b2,…,bk} such that b1=[a1,a2,…,ai1], b2=[ai1+1,ai1+2,…,ai2], …, bk=[aik−1+1,aik−1+2,…,an]. For example, array [10,3,2,3,2] can be partitioned as follows: {[10,3,2,3,2]} or {[10],[3],[2],[3],[2]}, or {[10],[3,2,3,2]}, or {[10,3],[2],[3,2]} and so on.
You are given array a of length n and integer m. Find the partition of a into maximum number of subarrays such that each subarray is m-good.

Input

The first line contains two integers n and m (1≤n≤5000, 1≤m≤5000) — length of array a and constant m.
The second line contains n integers a1, a2, …, an (1≤ai≤5000)— array a.

Output

If there is no valid partition of array a into m-good subarrays, print 0. Otherwise print maximum number of subarrays in partition of array a such that each subarray is m-good.

Examples
input

5 2
10 3 2 3 2

output

5

input

5 3
10 3 2 3 2

output

1

input

5 4
10 3 2 3 2

output

0

Note

In the first example array can be partitioned into 5 subarrays: {[10],[3],[2],[3],[2]}. Medians of each part greater of equal than 2.
In the second example we can’t partition array into several subarrays since medians of [2], [3,2], [2,3,2] and [3,2,3,2] are less than 3.

题目大意:

给你一场集合,你可以把它们隔开,然后取中位数(如果是偶数则取中间两个最小的),确保每个集合中位数都大于或等于k。问最多能有几个集合。

题目思路:

这道题a得好玄学哈哈
想想,把大于或等于的变成1,小于的变成-1,集合里有几个-1,就需要n+1个和它一个集合,剩余的1可以自成集合。所以集合数就等于这些1,-1加起来,就是答案。(想不到叭哈哈哈哈)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n[300010];

int main()
{
    ios::sync_with_stdio(false);
    int N, MAX;
    cin >> N >> MAX;
    for (int i = 1; i <= N; ++i)
    {
        cin >> n[i];
        if (n[i] >= MAX)
            n[i] = 1;
        else
            n[i] = -1;
    }
    int ans = 0;
    for (int i = 1; i <= N; ++i)
    {
        ans += n[i];
    }

    if (ans <= 0)
        cout << "0" << endl;
    else
        cout << ans << endl;
        
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43333395/article/details/89365464