2022杭电多校第三场
Cyber Language(模拟)
题意
将一个句子中每个单词的第一个字母大写。
分析
读入一行字符串可用getline
或fgets
,对每个字符串遍历所有字符,如果一个字符是小写字母且前一个字符是空格或者它是第一个字符,那么把它转大写输出,也可使用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;
}