2022杭电多校第三场题解

2022杭电多校第三场

在这里插入图片描述

Cyber Language(模拟)

题意
将一个句子中每个单词的第一个字母大写。

分析
读入一行字符串可用getlinefgets,对每个字符串遍历所有字符,如果一个字符是小写字母且前一个字符是空格或者它是第一个字符,那么把它转大写输出,也可使用stringstream

AC代码

写法一

int main()
{
	int t;
	cin>>t;
	string s;
	getline(cin,s);
	while(t--)
	{
		getline(cin,s);
		stringstream ss(s);
		string str;
		while(ss>>str)
		{
			cout<<(char)toupper(str[0]);
		}
		cout<<endl;
	}
	return 0;
}

写法二

#include<cstdio>
#include<cstring>
const int N=1000005;
int Case,n,i;char s[N];
int main(){
  fgets(s,N,stdin);
  sscanf(s,"%d",&Case);
  while(Case--){
    fgets(s,N,stdin);
    n=strlen(s);
    for(i=0;i<n;i++)
      if(s[i]>='a'&&s[i]<='z')
        if(!i||(i>0&&s[i-1]==' '))
          putchar(s[i]-'a'+'A');
    puts("");
  }
}

Package Delivery(贪心)

题意
邮局里有 n n n个包裹,每个包裹可在 [ l , r ] [l,r] [l,r]时间段内取。小Q每次最多取 k k k件包裹,每天可以去多次,求小Q去邮局取完所有快递的最小次数。

分析
首先,对于 r r r最小的区间,在第 r r r天取不会使答案变差,并且在第 r r r天必须去取快递。由于每次可以取 k k k件包裹,对于第 r r r天可以取的包裹优先选择右端点最小的包裹,右端点大的包裹有更大的选择空间。因此确定贪心策略:每次选择未取包裹中右端点最小的作为取货时间,将这一天可以取的包裹放入优先队列,优先选择右端点小的包裹。时间复杂度 O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))

AC代码

const int N=1e5+10;
struct node {
	int l,r;
}p[N];
int ql[N],qr[N],vis[N];
int n,k;

bool cmpl(int x,int y) { return p[x].l<p[y].l; }
bool cmpr(int x,int y) { return p[x].r<p[y].r; }

int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>k;
		for(int i=1;i<=n;i++) cin>>p[i].l>>p[i].r;
		for(int i=1;i<=n;i++) ql[i]=qr[i]=i,vis[i]=0;
		sort(ql+1,ql+n+1,cmpl);
		sort(qr+1,qr+n+1,cmpr);
		priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
		int j=1;
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			if(vis[qr[i]]) continue;
			while(j<=n&&p[ql[j]].l<=p[qr[i]].r)
			{
				q.push({p[ql[j]].r,ql[j]});
				j++;
			}
			ans++;
			int x=k;
			while(x--)
			{
				if(q.empty()) break;
				vis[q.top().second]=1;
				q.pop();
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

Two Permutations(DP)

题意
给定两个1~n的全排列P和Q,再给定一个长度为2n的序列S,每次从P和Q的最左端选一个元素放在一个初始为空的序列R的最右端,问有多少种方案使得R=S

分析
线性DP, f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]表示 R R R的第 i i i位和 P / Q P/Q P/Q匹配的方案数。注意到 P P P Q Q Q都是全排列,1~n每个元素在 P P P Q Q Q中只出现一次,可以在DP之前记录每个元素出现的位置。时间复杂度 O ( n ) O(n) O(n)

AC代码

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
const int mod=998244353;
const int N=3e5+10;
int a[N],b[N],pos1[N],pos2[N],c[N<<1];
ll f[N<<1][2];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i],pos1[a[i]]=i;
		for(int i=1;i<=n;i++) cin>>b[i],pos2[b[i]]=i;
		for(int i=1;i<=2*n;i++) cin>>c[i];
		for(int i=1;i<=2*n;i++) f[i][0]=f[i][1]=0;
		f[1][0]=(c[1]==a[1]);
		f[1][1]=(c[1]==b[1]);
		for(int i=2;i<=2*n;i++)
		{
			int x=pos1[c[i]];
			int y=pos2[c[i]];
			if(x+n>=i)
			{
				if(c[i-1]==a[x-1]) f[i][0]+=f[i-1][0];
				if(c[i-1]==b[i-x]) f[i][0]+=f[i-1][1];
			}
			if(y+n>=i)
			{
				if(c[i-1]==b[y-1]) f[i][1]+=f[i-1][1];
				if(c[i-1]==a[i-y]) f[i][1]+=f[i-1][0];
			}
			f[i][0]%=mod;
			f[i][1]%=mod;
		}
		cout<<(f[2*n][0]+f[2*n][1])%mod<<endl;
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值