Codeforces Round #807 (Div. 2)
A.Mark the Photographer
题目大意
要给2n个人拍照。把他们排成两排,每排n个人,要求是第二排的人要比他前面这个人高至少x。给定所有人身高,问能不能让他们站成符合要求的队形。
解题思路
贪心。先上结论:
能站成符合要求的队形 <==> 将身高从小到大排序后,对于从1到n的i,都有hn+i−x≥hi
可以这样证明:
1.假设现在有一个合法的队形如图所示,那么有a−b≥x和c−d≥x
2.倘若b≥c,不妨交换b,c位置
3.得到了一个新的队形,而这个新队形是一定合法的。因为a−c≥a−b≥x,且b−d≥c−d≥x。
上面的三步说明了一件事:即使有不是按我们这种贪心策略站的合法队形,这个合法队形也一定能转换成按贪心策略站的队形。(因为可以重复以上步骤,直到第二排的所有人都比第一排高)。然后结论就显然了。
具体代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, x;
int h[N];
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
cin >> n >> x;
for (int i = 1; i <= n << 1; i++)
cin >> h[i];
sort(h + 1, h + n * 2 + 1);
bool flag = true;
for (int i = 1; i <= n; i++)
{
if (h[i + n] - x < h[i])
{
cout << "NO" << '\n';
flag = false;
break;
}
}
if (flag)
cout << "YES" << '\n';
}
return 0;
}
B.Mark the Dust Sweeper
题目大意
有n个房间要清理,编号1到n,每个房间有ai的垃圾,每次清扫可以选择i,j(i≤j且要求ai,ai+1……aj−1都大于零),使得ai减一,aj加一。问至少清理几次能使得除了最后一个房间外的别的房间都没有垃圾。
解题思路
要把垃圾都扫到最后一个房间,如果不考虑(要求ai,ai+1……aj−1都大于零)这个要求,那么ans=∑n−1i=1ai。然后再思考这个要求,其实就是多了填充0的步数,每填充一个0需要消耗一步,所以ans+=∑n−1i=l(ai==0)。l是第一个ai大于0的位置。
具体代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; //记得开LL
const int N = 2e5 + 10;
int n;
int a[N];
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
LL ans = 0;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
int l = 1;
while (a[l] == 0)
l++;
for (int i = 1; i <= n - 1; i++)
ans += (LL)a[i];
for (int i = l; i <= n - 1; i++)
ans += (LL)(a[i] == 0);
cout << ans << '\n';
}
return 0;
}
C.Mark and His Unfinished Essay
题目大意
给一个字符串s,可以进行若干次复制粘贴操作。每次复制粘贴操作可以选中s[l,r],把它粘贴到字符串末尾。所有复制粘贴操作结束后会给若干询问,给一个k,问s[k]是什么字符
解题思路
数据范围很大,说明题意不是要真的模拟去把最后的字符串求出来。那么题目考察的应该是怎么对询问优化。
为了清晰可以看看如图这种情况,是复制粘贴了三次。现在要查询s[k],先跳到蓝串本来的位置,发现这里正好也在绿串上,那么再跳回绿串本来的位置上,发现这里已经是黑串(即原串)上,那么就找到答案了。想到这里代码实现就不难了。
具体代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, c, q;
string s;
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
cin >> n >> c >> q >> s;
vector<LL> l(c + 1), r(c + 1), d(c + 1);
l[0] = 0;
r[0] = n;
for (int i = 1; i <= c; i++)
{
LL a, b;
cin >> a >> b;
a--, b--;
l[i] = r[i - 1];
r[i] = l[i] + (b - a + 1);
d[i] = l[i] - a;
}
while (q--)
{
LL k;
cin >> k;
k--;
for (int i = c; i >= 1; i--)
{
if (k < l[i])
continue;
else
k -= d[i];
}
cout << s[k] << '\n';
}
}
return 0;
}