[codeforces 1330B] Dreamoon Likes Permutations 合理分块

Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!   比赛人数10889

[codeforces 1330B]  Dreamoon Likes Permutations  合理分块

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1330/problem/B

ProblemLangVerdictTimeMemory
B - Dreamoon Likes Permutations GNU C++11Accepted77 ms2200 KB

比赛时,没有思路,最好的办法就是,拿出纸笔,模拟样例数据生成过程

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次
不符题意,无需再做后面的操作。

比赛时,代码写得一团糟,第一次提交WA,反复读题,觉得思路没有问题,每组输入数据,对应的输出数据的第一行输出情况,只有0,1,2,三种情况。

举些数据,突然想到神来一笔,找到关键数据如下

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

若上述数据能通过,该题的坑点也就跳过去了。

修改代码,提交AC.

比赛时,虽然提交的代码效率高,但感觉可读性差了许多,以下AC代码,为赛后重写代码,可读性高了许多。

#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;
}

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值