(不好!)7.11训练(codeforce1249

CodeForces 1249A

You are a coach of a group consisting of n students. The i-th student has programming skill ai. All students have distinct programming skills. You want to divide them into teams in such a way that:

No two students i and j such that |ai−aj|=1 belong to the same team (i.e. skills of each pair of students in the same team have the difference strictly greater than 1);
the number of teams is the minimum possible.
You have to answer q independent queries.

Input
The first line of the input contains one integer q (1≤q≤100) — the number of queries. Then q queries follow.

The first line of the query contains one integer n (1≤n≤100) — the number of students in the query. The second line of the query contains n integers a1,a2,…,an (1≤ai≤100, all ai are distinct), where ai is the programming skill of the i-th student.

Output
For each query, print the answer on it — the minimum number of teams you can form if no two students i and j such that |ai−aj|=1 may belong to the same team (i.e. skills of each pair of students in the same team has the difference strictly greater than 1)

Example
Input
4
4
2 10 1 20
2
3 6
5
2 3 4 99 100
1
42
Output
2
1
2
1
Note
In the first query of the example, there are n=4 students with the skills a=[2,10,1,20]. There is only one restriction here: the 1-st and the 3-th students can’t be in the same team (because of |a1−a3|=|2−1|=1). It is possible to divide them into 2 teams: for example, students 1, 2 and 4 are in the first team and the student 3 in the second team.

In the second query of the example, there are n=2 students with the skills a=[3,6]. It is possible to compose just a single team containing both students.
题意:给你数字让你分组,其中不能让 相差为一的数在一个组。
思路:无非就1个 2 个组就行啊,有相邻的数就分俩,else 分一个

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	int t; cin >> t;
	while (t--)
	{
		int n; cin >> n;
		int a[1000];
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		int ans = 1;
		sort(a + 1, a + 1 + n);
		for (int i = 2; i <= n; i++)
		{
			if (a[i] - a[i - 1] == 1)
			{
				ans = 2; break;
			}
		}
		cout << ans << endl;
	}
}

CodeForces 1249B1

The only difference between easy and hard versions is constraints.

There are n kids, each of them is reading a unique book. At the end of any day, the i-th kid will give his book to the pi-th kid (in case of i=pi the kid will give his book to himself). It is guaranteed that all values of pi are distinct integers from 1 to n (i.e. p is a permutation). The sequence p doesn’t change from day to day, it is fixed.

For example, if n=6 and p=[4,6,1,3,5,2] then at the end of the first day the book of the 1-st kid will belong to the 4-th kid, the 2-nd kid will belong to the 6-th kid and so on. At the end of the second day the book of the 1-st kid will belong to the 3-th kid, the 2-nd kid will belong to the 2-th kid and so on.

Your task is to determine the number of the day the book of the i-th child is returned back to him for the first time for every i from 1 to n.

Consider the following example: p=[5,1,2,4,3]. The book of the 1-st kid will be passed to the following kids:

after the 1-st day it will belong to the 5-th kid,
after the 2-nd day it will belong to the 3-rd kid,
after the 3-rd day it will belong to the 2-nd kid,
after the 4-th day it will belong to the 1-st kid.
So after the fourth day, the book of the first kid will return to its owner. The book of the fourth kid will return to him for the first time after exactly one day.

You have to answer q independent queries.

Input
The first line of the input contains one integer q (1≤q≤200) — the number of queries. Then q queries follow.

The first line of the query contains one integer n (1≤n≤200) — the number of kids in the query. The second line of the query contains n integers p1,p2,…,pn (1≤pi≤n, all pi are distinct, i.e. p is a permutation), where pi is the kid which will get the book of the i-th kid.

Output
For each query, print the answer on it: n integers a1,a2,…,an, where ai is the number of the day the book of the i-th child is returned back to him for the first time in this query.

Example
Input
6
5
1 2 3 4 5
3
2 3 1
6
4 6 2 1 5 3
1
1
4
3 4 1 2
5
5 1 2 4 3
Output
1 1 1 1 1
3 3 3
2 3 3 2 1 3
1
2 2 2 2
4 4 4 1 4
题意:一群小朋友交换书籍,问你多少次能再次回到自己的手中,没个人都有a[i] 代表给 谁 如果a[i]=1,代表给自己。
思路:就是每个人都看就可以,每个人的都去遍历就可以了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;

int main()
{
	int t; cin >> t;
	while (t--)
	{
		int a[2000];
		int n; cin >> n;
		for (int i =1; i <=n; i++)
			cin >> a[i];
		int ans = 1;
		for (int i = 1, x = 1; i <=n;i++, x++)
		{
			ans = 1;
			while (i <= n)
			{
				i = a[i];
				if (x == i)
					break;
				ans++;
			}
			cout << ans <<" ";
		}
		cout << endl;
	}
}

CodeForces 1249B2※※※※※※※※※※

这个题目与前一题的区别是n的值变大了 n (1≤n≤2⋅10的5次方)
思路:如果再用上一题的话就得超时了啊!得换了
根据题意可知如果1->3->4->1,那么134走到本身都需要4步,所以在找第
一条路需要走的步数时,可以将路上遇见的所有点所需的步数全部得出。
只需用一个队列(或者栈),将路上遇见的所有点全部存进去,队列(或者栈)中元素个数就是步数,然后一个一个的赋值。
意思就是 在一个循环圈的 步数都是一样的!!!!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[300000], b[300000];
int main()
{
	int t; cin >> t;
	while (t--)
	{
		int n; cin >> n;
		memset(b, 0, sizeof b);
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		queue<int>q;
		for (int i = 1; i <= n; i++)
		{
			if (b[i]==0)
			{
				int m = i;
				q.push(m);
				m = a[m];
				while (m != i)
				{
					q.push(m);
					m = a[m];
				}
				int ans = q.size();
				while (!q.empty())
				{
					b[q.front()] = ans;
					q.pop();
				}
			}
		}
		for (int i = 1; i <= n; i++)	
				cout << b[i]<<" ";
		cout << endl;
	}
	

}

CodeForces - 1249C1

点我 啊
The only difference between easy and hard versions is the maximum value of n.

You are given a positive integer number n. You really love good numbers so you want to find the smallest good number greater than or equal to n.

The positive integer is called good if it can be represented as a sum of distinct powers of 3 (i.e. no duplicates of powers of 3 are allowed).

For example:

30 is a good number: 30=33+31,
1 is a good number: 1=30,
12 is a good number: 12=32+31,
but 2 is not a good number: you can’t represent it as a sum of distinct powers of 3 (2=30+30),
19 is not a good number: you can’t represent it as a sum of distinct powers of 3 (for example, the representations 19=32+32+30=32+31+31+31+30 are invalid),
20 is also not a good number: you can’t represent it as a sum of distinct powers of 3 (for example, the representation 20=32+32+30+30 is invalid).
Note, that there exist other representations of 19 and 20 as sums of powers of 3 but none of them consists of distinct powers of 3.

For the given positive integer n find such smallest m (n≤m) that m is a good number.

You have to answer q independent queries.

Input
The first line of the input contains one integer q (1≤q≤500) — the number of queries. Then q queries follow.

The only line of the query contains one integer n (1≤n≤104).

Output
For each query, print such smallest integer m (where n≤m) that m is a good number.

Example
Input
7
1
2
6
13
14
3620
10000
Output
1
3
9
13
27
6561
19683
题意:找一个比n大的数字,这个数字能可以被3的幂的和来表示,但是 3的幂不能重复。
思路:若xi没有重复,则反复令n/=3,每次n%3得到的都应该是0或者1。反之,若n不是好数,则在n/=3的过程中,一定会出现n%3=2的情况,籍此可以作为判断依据。
参考的博主链接。
在这里插入图片描述在这里插入图片描述

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	int t; cin >> t;
	while (t--)
	{
		int n; cin >> n;
		while (1)
		{
			int f = 1, m = n;
			while (m)
			{
				if (f && m % 3 == 2)
					f = 0;
				m = m / 3;
			}
			if (f) break;
			n++;
		}
		cout << n << endl;	
	}
}

更好的思路:

首先我们可以求出 3的不同次数,之后我们可以先找到一个由 3( 1到 k)的幂数和( sum)且大于已知的数 n;
但这不一定是我们的最优解,
所以把 sum 减去 3的各个幂次(从大到小)
且保证 sum 减去之后还需要大于等于n 即可;
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	int t; cin >> t;
	while (t--)
	{
		ll n; cin >> n;
		ll sum = 0, x = 1;
		while (sum < n)
		{
			sum += x; x *= 3;
		}
		while(x)
		{
			if (sum - x >= n)
				sum -= x;
			x = x / 3;
		}
		cout << sum << endl;
		
	}
	

}

CodeForces 1249C2

这个就是N更大了 上边的c1第二个思路能够AC

CodeForces - 1249D1(not understand)

点我、
The only difference between easy and hard versions is constraints.

You are given n segments on the coordinate axis OX. Segments can intersect, lie inside each other and even coincide. The i-th segment is [li;ri] (li≤ri) and it covers all integer points j such that li≤j≤ri.

The integer point is called bad if it is covered by strictly more than k segments.

Your task is to remove the minimum number of segments so that there are no bad points at all.

Input
The first line of the input contains two integers n and k (1≤k≤n≤200) — the number of segments and the maximum number of segments by which each integer point can be covered.

The next n lines contain segments. The i-th line contains two integers li and ri (1≤li≤ri≤200) — the endpoints of the i-th segment.

Output
In the first line print one integer m (0≤m≤n) — the minimum number of segments you need to remove so that there are no bad points.

In the second line print m distinct integers p1,p2,…,pm (1≤pi≤n) — indices of segments you remove in any order. If there are multiple answers, you can print any of them.

Examples
Input
7 2
11 11
9 11
7 8
8 9
7 8
9 11
7 9
Output
3
1 4 7
Input
5 1
29 30
30 30
29 29
28 30
30 30
Output
3
1 2 4
Input
6 1
2 3
3 3
2 3
2 2
2 3
2 3
Output
4
1 3 5 6
题意:给多组线段,而每一个点的覆盖次数不超过K,每次可去除一个线段,问最少去多少线段以及线段的位置。
思路:用差分数组找到每个点的覆盖次数,若超过k次则去掉几个右边较大的(因为是从左到右,所以不用考虑左边 PS :没大明白这思路的实施代码啊!!!!

CodeForces - 1249D2()

和上题相比就是多了约束条件

反思:今天训练完就出去玩了,题解写的太差了,如果比赛的时候不好好看题,赛后再看题解啥的 感觉 效果很差,这个确实太差了就AC了俩题,而且这几次训练都有一些题 都是比较容易出来的,但我还是有疑惑点,在题解里面都标注了,周末再继续看!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值