Educational Codeforces Round 67 (Rated for Div. 2)



A. Stickers and Toys(思维)

原题链接:https://codeforces.com/contest/1187/problem/A


题意:

有n个神秘礼盒, 每个礼盒装着以下三种类型的物品:

  1. 一个贴纸
  2. 一个玩具
  3. 一个贴纸和一个玩具

已知贴纸共t个,玩具共s个,求问至少开几个箱子才能够保证一定至少能获得一个玩具和一个贴纸。

思路: 可以把所有情况都列出来,共有4种情况:

  1. (s+t)==n
  2. (s<n&&t<n) && (s+t>n)
  3. (s==n && t<n) || (s<n && t == n)
  4. s==n && t ==n

然后会发现,前三种情况的答案都是 n - min(s, t) + 1。第四种特判一下即可。


Code(C++):

#include <iostream> 
using namespace std;
int main(){
	int k;	cin>>k;
	while(k--){
		int n,s,t;
		cin>>n>>s>>t;
		if(s==n&&t==n)
			cout<<1<<endl;
		else
			cout<<n-min(s,t)+1<<endl;
	}
	return 0;
}


B. Letters Shop(思维)

原题链接:https://codeforces.com/contest/1187/problem/B

题意: 给定一个字符串 s,含有 n 个小写字母。m 次询问:给定一个字符串 t,问至少使用 s 的前几个字符可以构造出 t 。字符可以有多余,但必须够用。

思路: 先记录 s[i] 在 s 中的位置 i 出现cnt1次,然后记录询问的字符串中 t[i] 出现 cnt2 次,最后不断更新 t[i] 在 s 中出现的最大位置。


Code(C++):

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=2e5+100;
int sum[30][N],sum1[30],sum2[30];
int main(){
	int n;	cin>>n;
	string s;	cin>>s;
	for(int i=0;i<n;i++)
		sum[s[i]-'a'][++sum1[s[i]-'a']]=i;	//s[i]在s中的位置i出现cnt1次
	int m;	cin>>m;
	while(m--){
		memset(sum2,0,sizeof(sum2));
		string t;	cin>>t;
		int len=t.size();
		int ans=0;
		for(int i=0;i<len;i++)	 
			++sum2[t[i]-'a'];	//t[i]出现cnt2次
		for(int i=0;i<26;i++)
			ans=max(ans,sum[i][sum2[i]]);	//不断更新t[i]在s中出现的最大位置
		cout<<ans+1<<endl; 
	}
	return 0;
}

Code(Java):

import java.util.Scanner;
public class Main {
	private static final int N = (int) 2e5+100;
	static int[][] sum = new int[30][N];
	static int[] sum1 = new int[30];
	static int[] sum2 = new int[30];
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int n = cin.nextInt();
		String s = cin.next();
		for(int i=0;i<n;i++) 
			sum[s.charAt(i)-'a'][++sum1[s.charAt(i)-'a']]=i;
		int m = cin.nextInt();
		while(m-- >0) {
			for(int i=0;i<30;i++)
				sum2[i] = 0;
			String t = cin.next();
			int len = t.length();
			int ans=0;
			for(int i=0;i<len;i++)
				++sum2[t.charAt(i)-'a'];
			for(int i=0;i<26;i++)
				ans = Math.max(ans, sum[i][sum2[i]]);
			System.out.println(ans+1);
		}
	}
}


C. Vasya And Array(贪心+构造)

原题链接: https://codeforces.com/contest/1187/problem/C


题意: 给定数组a的长度 n , 有 m 个要求,给出 ti ,li ,ri,要求构造数列:

  1. ti == 1,在数组区间为 [li, ri] 是非递减的,即上升或相等序列。
  2. ti == 0,在数组区间为 [li, ri] 不是非递减的,即下降序列。

思路:

  1. 先把 t==1 的情况处理掉,上升或相等序列,例如序列 3 3 3 3 3,是符合的。把非递减的位置用 b[i] 标记为1,表示a[i] <= a[i-1]。
  2. 再来处理 t==0 的情况,下降序列,如果存在一个 b[i]!=1 ,即 a[i]>a[i-1],则符合要求。如果一个都不存在,则用vis标记出来,然后输出“NO”后直接结束程序。
  3. 然后给序列第一个数赋一个足够大的数,至少要大于1000,根据 b[i] 标记,遍历给序列赋值。
  4. 最后遍历输出序列。

Code1(C++):

#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e3+10;
int b[N],ans[N];
struct node{
	int t,l,r;
	bool operator < (const node &p){	//学习大佬的码风!!!
		return t > p.t;
	}
}a[N];
int main(){
	int n,m;	
	cin>>n>>m;
	for(int i=1;i<=m;i++)	
		cin>>a[i].t>>a[i].l>>a[i].r;
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++){
		if(a[i].t==1){
			for(int j=a[i].l+1;j<=a[i].r;j++)
				b[j]=1;
		}else{
			bool vis=false;
			for(int j=a[i].l+1;j<=a[i].r;j++){
				if(b[j]!=1){
					vis=true;
					break;
				}
			}
			if(!vis){
				cout<<"NO"<<endl;
				return 0;
			}
		}
	}
	ans[1]=1500;
	for(int i=2;i<=n;i++){
		if(b[i]==1)		//不下降序列,此处是相等序列 
			ans[i]=ans[i-1];
		else			//上升序列 
			ans[i]=ans[i-1]-1;
	}
	cout<<"YES"<<endl;
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值