10月13日考试复盘

T1 对面对面

这题本质不难,只是要考虑周全才行。

1.我们可以发现,我们可以用a和b推出总和来,n=abs(a-b)*2

因为a和b是对应的两个数,它们相减就为总长度的一半

2.那什么时候,无解呢?当a,b,c其中有一个大于n的时候

为什么?因为你其中一个比最大的还大了,不就矛盾了吗?

3如果c大于n/2时,我们可以发现,因为c在左边,所以它

对应的值在c的右边,为(c-n/2).反之则可推出,c小于n/2时

答案为(c+n/2)。

比较简单我就不放代码了


T2 K段区间 

这道题不难,但有点坑

错误示范:

一开始看到这题的描述时,我立马想到了这不就是求是否能划为<=k个递增子段吗(因为能划为小于k段一定能划为k段)?

于是我用for循环来遍历一遍再判断,如果当前的不大于前一个res++;

然后我这么试了一下发现可以过样例,就没管了。

可实际上是有问题的

就比如1 5 7 9 3

按这么做是分两段对吧

可实际上要分三段(3要插进1 5 7 9之中)

所以要这么做:

先sort()排一遍序(因为要保证求出来的值可以满足顺序能排)

再判断于是我用for循环来遍历一遍再判断,如果当前的序号不大于前一个res++;

放代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+98764;
int n,m,T,k;
struct node{
	int v;
	int id;
}a[N];
bool cmp(node a,node b){
	return a.v < b.v;
}
string work(){
	int res=1;
	cin >> n >> k;
	for(int i=1;i<=n;i++){
		cin >> a[i].v;
		a[i].id=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<n;i++){
		if(a[i].id+1 != a[i+1].id){
			res++;
		}
	}
	if(res <= k){
		return "YES";
	}else{
		return "NO";
	}
}
int main(){
	cin >> T;
	while(T--){
		cout << work() << endl;
	}                                                                                                            
	return 0;
} 

T3 括号分割 

这题也不难,只是要想到那一点:

我们发现嵌在一起的括号在算答案的时,只要看有几个可划分的空。

根据乘法原理就有2^res种(每个空有选和不选,2种情况)

还要记得取模1e9+7

放代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,m,T,k;
long long res=0,ans=1,re1=0,re2=0;
string s;
int main(){
	cin >> s;
	n = s.size();
	for(int i=0;i<n;i++){
		if(s[i] == '('){
			re1++;
		}else if(s[i] == ')'){
			re2++;
		}
		if(re1 == re2){
			res++;
		}
	}
	for(int i=1;i<=res-1;i++){
		ans = ans*2%mod;
	}        
	cout << ans;                                                                   
	return 0;
} 

T4 最长串 

这是一道线性dp题

状态:

dp[i]表示以第i个字符为结尾的最大拼接长度

状态转移:

	for(int i=1;i<=n;i++){
		cin >> s[i];
		dp[s[i][s[i].size()-1]] = max(dp[s[i][s[i].size()-1]],int(dp[s[i][0]] + s[i].size()));
	}

答案:

for(int i=1;i<=n;i++)
		res=max(res,dp[s[i][s[i].size()-1]]);

初始状态:

dp[i]=0;

memset(dp,0,sizeof(dp));

放代码:

 

#include<bits/stdc++.h>
using namespace std;
const int N=2e5;
int n,m,T,k,res;
int dp[130];
string s[N];
int work(){
	memset(dp,0,sizeof(dp));
	res=0;
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> s[i];
		dp[s[i][s[i].size()-1]] = max(dp[s[i][s[i].size()-1]],int(dp[s[i][0]] + s[i].size()));
	}
	for(int i=1;i<=n;i++)
		res=max(res,dp[s[i][s[i].size()-1]]);
	return res;
}
int main(){
	cin >> T;
	while(T--){
		cout << work() << "\n";
	}                                                                  
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值