codeforces 869(div2)AB

作者参加了一场Codeforces的编程竞赛,完成了A、B两题,对于A题,理解题目花费了一些时间,但最终实现了一个保留与一号相同元素的算法;B题是一个构造题,通过分析得出奇数项无解,偶数项有解的规律。未能解决的C题可能涉及最长上升子序列的优化解法,如使用前缀和。
摘要由CSDN通过智能技术生成

利用今天上午时间vp了这场,打了1小时,做出来了AB,然后肚子饿死而且我感觉C题做不出来,所以我就去吃饭了,吃完饭后,就去宿舍睡了一觉,回来做C题还是没思路,最后排名4500/17000,我感觉还行,自己是越来越适应cf的题目了。

A:Problem - A - Codeforces (Unofficial mirror by Menci)

题意还是很难看懂,看了好几遍才有了点思路,然后一边写一边思考(坏毛病),写了一会发现有思路了,我(即1号)最后一定要保留下来,所以题目的意思就是所有和一号相同的都保留下来,其他的离开,最后A题13分就出来了

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
string s[105];
int t,n,k;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&k);
		for(int i=0;i<n;i++){
			cin>>s[i];
		}
		int ans=1;
		for(int i=1;i<n;i++){
			if(s[i]==s[0]){
				ans++;
			}
		}
		printf("%d\n",ans);	
	}

	return 0;
}

B:Problem - B - Codeforces (Unofficial mirror by Menci)

感觉是一个构造题目,说实话比赛的时候没想这么多,就直接做了....自己写了几组数据发现如果n为奇数一定没有答案(1除外),因为等差数列前n项和为n*(n+1)/2,n为奇数时候,n+1为偶数,能整除...然后我感觉偶数的时候一定有答案,然后就试了试4,6,然后自己造的答案不对,自己误认为对了....然后期交了几发不对,然后又开始想,对n=4的所有情况都列举出来了,发现3 4 1 2是可以的,如果n=6,5 6 3 4 1 2也是可以的...所以就出答案了

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t;
int main(){
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		if(n==1){
			printf("1\n");
			continue;
		}
		if(n%2==1){
			printf("-1\n");
			continue;
		}else{
			for(int i=n-1,j=n;i>=1,j>=1;i=i-2,j=j-2){
				printf("%d %d ",i,j);
			}
			printf("\n");
		}
}
	return 0;
}

 C:感觉这题跟最长上升子序列有关,就想到了dp,因为这题跟dp有有点区别所以状态表示为dp[i][j][0/1],dp[i][j][1]表示a[j-1]>=a[j],dp[i][j][0]表示a[j-1]<a[j],然后显然不能通过,因为双层循环肯定超时,所以就想着优化为一层循环,没啥思路,而且大脑很混乱啊....

正确思路:前缀和(这能用前缀和做?我蒙圈....):

参考:Codeforces Round 869 (Div. 2) A-D题解-云海天教程

设如果a[i-2]>=a[i-1]>=a[i],s[i]=s[i-1]+1,否则s[i]=s[i-1];

如果区间长度(r-l+1<3)直接输出r-l+1即可;

否则输出(r-l+1-(s[r]-s[l+1]))即可,正常来说应该  -(s[r]-s[l-1]);

这里的s[r]表示a[r-2],a[r-1],a[r],正好到a[i];

这里的s[l+1]表示s[l-1],s[l].s[l+1],末尾是s[l-1];

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int a[200005];
int n,q;
int s[200005];
int main(){
		scanf("%d%d",&n,&q);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=3;i<=n;i++){
			if(a[i]<=a[i-1]&&a[i-1]<=a[i-2]){
				s[i]=s[i-1]+1;
			}else{
				s[i]=s[i-1];
			}
		}
		int l,r;
		for(int i=1;i<=q;i++){
			cin>>l>>r;
			if(r-l+1<3){
				printf("%d\n",r-l+1);
			}else{
				printf("%d\n",r-l+1-(s[r]-s[l+1])); 
			}
	}
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值