Codeforces Round #776 (Div. 3)
A. Deletions of Two Adjacent Letters
Description
已知一个字符串 \(s\) 和一个字符 \(c\)。每次可以从 \(s\) 中删除两个相邻的字符,问是否能够最终剩下一个字符 \(c\)。保证 \(|s|\) 为奇数。
Solution
很明显,\(s\) 的第 \(i\) 个字符 \(s_i\) 能够最终留下的充要条件为 \(i\) 为奇数,即左边有偶数个字符,右边也有偶数个字符。那么我们就可以查找 \(s\) 中的每个 \(c\),判断是否符合条件即可。
Code
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int T;
string s;
char c;
cin>>T;
while(T--)
{
cin>>s>>c;
bool flag=0;
for(int i=0;i<s.size();i++)
if(s[i]==c&&i%2==0&&(s.size()-i-1)%2==0)
{
flag=1;
break;
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
B. DIV + MOD
Description
定义函数 \(f_a(x)=\lfloor\frac x a\rfloor+x\bmod a\),给出 \(a\)、\(l\)、\(r\),求 \(f_a(x)\) 在 \([l,r]\) 内的最大值。
Solution
这个函数是由两个量相加而成,因此它在一个区间内的最大值只有下面几种可能:(下面所有的“这个数”均指在区间内使得 \(f_a(x)\) 最大的 \(x\))
- \(\lfloor\frac x a\rfloor\) 最大,在此前提下使得 \(x\bmod a\) 最大。那么这个数就是 \(r\),很明显它满足上面的两个条件。计算结果为 \((\lfloor\frac r a\rfloor+r\bmod a)\);
- \(x\bmod a\) 最大,在此前提下使得 \(\lfloor\frac x a\rfloor\) 最大。此时要分两种情况讨论:
- \(\lfloor\frac l a\rfloor=\lfloor\frac r a\rfloor\),即区间内所有数除以 \(a\) 向下取整的结果都相同,那么这个数还是 \(r\),计算结果依然为 \((\lfloor\frac r a\rfloor+r\bmod a)\);
- \(\lfloor\frac l a\rfloor<\lfloor\frac r a\rfloor\),那么这个数就是 \((r-1-r\bmod a)\),就是退一步,把 \(\lfloor\frac x a\rfloor\) 减小 \(1\),再让 \(x\bmod a\) 拉满,让它等于 \((a-1)\)。计算结果为 \((\lfloor\frac x a\rfloor+a-2)\)。
综上所述,答案就是
\[\begin{cases}\lfloor\frac r a\rfloor+r\bmod a&,\lfloor\frac l a\rfloor=\lfloor\frac r a\rfloor\\\max(\lfloor\frac r a\rfloor+r\bmod a,\lfloor\frac x a\rfloor+a-2)&,\lfloor\frac l a\rfloor<\lfloor\frac r a\rfloor\end{cases}
\]
Code
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int l,r,a;
scanf("%d%d%d",&l,&r,&a);
if(l/a==r/a) printf("%d\n",r/a+r%a);
else printf("%d\n",max(r/a+r%a,r/a+a-2));
}
return 0;
}
C. Weight of the System of Nested Segments
Description
数轴上有 \(m\) 个点,每个点都有一个坐标 \(x_i\) 和权值 \(w_i\)。
定义一个线段序列 \([l_1,r_1],[l_2,r_2],\dots,[l_n,r_n]\) 为嵌套线段系统当 \([l_{i+1},r_{i+1}]\) 被严格嵌套在 \([l_i,r_i]\) 中。现在需要从中选出 \(2n\) 个点,组成 \(n\) 条线段,使其为嵌套线段系统,且所有端点权值和最小。求这个系统。
Solution
事实上,不需要理睬什么嵌套线段系统,只需要从 \(m\) 个点中选出权值最小的 \(2n\) 个,这样它们的和必定最小,然后一首一尾输出原编号即可。
Code
#include<bits/stdc++.h>
using namespace std;
struct point{int x,w,id;}p[200005];
inline bool cmp(const point& a,const point& b)
{
return a.w<b.w;
}
inline bool cmp2(const point& a,const point& b)
{
return a.x<b.x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&p[i].x,&p[i].w),p[i].id=i;
sort(p+1,p+m+1,cmp);//取权值最小的 2n 个点
sort(p+1,p+n*2+1,cmp2);//将取出的 2n 个点按照坐标排序
int ans=0;
for(int i=1;i<=n*2;i++) ans+=p[i].w;
printf("%d\n",ans);
for(int i=1;i<=n;i++) printf("%d %d\n",p[i].id,p[n*2-i+1].id);
puts("");
}
return 0;
}