[codeforces 1330B] Dreamoon Likes Permutations reasonable division

Codeforces Round # 631 (Div. 2)-Thanks, Denis aramis Shitov!   Number of players 10889

[codeforces 1330B] Dreamoon Likes Permutations reasonable division

See https://blog.csdn.net/mrcrack/article/details/103564004 for the general catalog

Online evaluation address https://codeforces.com/contest/1330/problem/B

Problem Just Verdict Time Memory
B - Dreamoon Likes Permutations GNU C ++ 11 Accepted 77 ms 2200 KB

During the competition, there is no idea, the best way is to take out the pen and paper and simulate the sample data generation process

5
1 4 3 2 1

2
1 4
4 1
模拟发现,对应排列数
1
4 3 2 1
1出现2次
1 4 3 2
1
1出现2次
一组排列数含1个元素,另一组排列数含4个元素
可这样分组,按自左往右序列,分成1个元素(最左边有1个元素);5-1=4个元素(最左边有4个元素).这两种情况。如下:
(1) (4 3 2 1)此种情况正确
(1 4 3 2) (1)此种情况正确


6
2 4 1 3 2 1

1
4 2
模拟发现,对应排列数
2 4 1 3
2 1
1出现2次,2出现2次
一组排列数含2个元素,另一组排列数含4个元素
可这样分组,按自左往右序列,分成2个元素(最左边有2个元素);6-2=4个元素(最左边有4个元素).这两种情况。如下:
(2 4) (1 3 2 1)此种情况错误
(2 4 1 3) (2 1)此种情况正确

4
2 1 1 3

0
模拟发现,找不到,对应排列数
1出现2次
一组排列数含2个元素,另一组排列数含2个元素
可这样分组,按自左往右序列,分成2个元素(最左边有2个元素);4-2=2个元素(最左边有2个元素).这两种情况。如下:
(2 1) (1 3)此种情况错误
(2 1) (1 3)此种情况错误


4
1 3 3 1

0
模拟发现,找不到,对应排列数
1出现2次,3出现2次
一组排列数含1个元素,另一组排列数含3个元素
可这样分组,按自左往右序列,分成1个元素(最左边有1个元素);4-1=3个元素(最左边有3个元素).这两种情况。如下:
(1) (3 3 1)此种情况错误
(1 3 3) (1)此种情况错误


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

1
2 10
模拟发现,对应排列数
2 1
3 4 5 6 7 8 9 1 10 2
1出现2次,2出现2次
一组排列数含2个元素,另一组排列数含10个元素
可这样分组,按自左往右序列,分成2个元素(最左边有2个元素);12-2=10个元素(最左边有10个元素).这两种情况。如下:
(2 1) (3 4 5 6 7 8 9 1 10 2)此种情况正确
(2 1 3 4 5 6 7 8 9 1) (10 2)此种情况错误

3
1 1 1

0
模拟发现,找不到,对应排列数
1出现3次
不符题意,无需再做后面的操作。

During the game, the code was a mess. I submitted WA for the first time and read the questions repeatedly. I felt that there was no problem with the idea. The input data of each group and the corresponding output data in the first line of the output were only 0,1,2,3.

To cite some data, I suddenly thought of a stroke of God and found the key data as follows

Input:
1
4
1 2 2 1
Output:
1
2 2

If the above data can pass, the pit of the problem will also be skipped.

Modify the code and submit to AC.

During the competition, although the submitted code is highly efficient, it feels much less readable. The following AC code rewrites the code after the game, making it much more readable.

#include <cstdio>
#include <algorithm>
#define maxn 200010
using namespace std;
int a[maxn],cnt[maxn],n,b[maxn];//b[]临时数组
int judge(int l,int r){//返回值0表明a[]在[l,r]区间的元素,不能构成排列数.返回值1表明a[]在[l,r]区间的元素,能构成排列数
	int i,m;
	m=r-l+1;
	for(i=1;i<=m;i++)b[i]=a[l+i-1];
	sort(b+1,b+1+m);//自小到大排序
	for(i=1;i<=m;i++)
		if(b[i]!=i)return 0;//判定b[]在[l,r]区间,是否是排列数
	return 1;
}
int main(){
	int t,i,b,k,l1,r1,l2,r2;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=n;i++)cnt[i]=0;
		for(i=1;i<=n;i++)scanf("%d",&a[i]),cnt[a[i]]++;
		b=0;
		for(i=1;i<=n;i++)
			if(cnt[i]==2)b=i;//记录最短排列数中元素的最大值
			else break;
		if(b==0)printf("0\n");
		else{
			k=0,l1=0,r1=0,l2=0,r2=0;
			if(judge(1,b)&&judge(b+1,n))k++,l1=b,r1=n-b;
			if(judge(1,n-b)&&judge(n-b+1,n))k++,l2=n-b,r2=b;
			if(k==2){
				if(b==n-b){//可能遇到排列数元素个数相同的情况。
					printf("1\n");
					printf("%d %d\n",b,n-b);
				}else{
					printf("2\n");
					printf("%d %d\n",b,n-b);
					printf("%d %d\n",n-b,b);
				}
			}else if(k==1){//需判定该输出b n-b,还是n-b b
				printf("1\n");
				if(l1)printf("%d %d\n",l1,r1);
				else printf("%d %d\n",l2,r2);
			}else printf("0\n");//找不到排列数
		}
	}
	return 0;
}

 

 

Published 660 original articles · praised 562 · 480,000 views

Guess you like

Origin blog.csdn.net/mrcrack/article/details/105307964