A. Permutation Forgery
输入的数组倒序输出即可。。。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
const ll mod = 1e6 + 1e6+5;
ll INF = 1e18;
ll ans = 0;
int dataa[mod] = {};
int tmpa[mod] = {};
int min(int b, int a) { if (a > b)return b; return a; }
int main()
{
ll n;
cin >> n;
while (n--)
{
ll m;
cin >> m;
for (int i = 0; i < m; i++)scanf("%d", &dataa[i]);
for (int i = m - 1; i >= 0; i--)printf("%d ", dataa[i]);
printf("
");
}
}
B. Array Cancellation
给定一个总和为0的有正负数的数列。可以进行以下操作:
选定两个数一个加一一个减一,如果加一的数在减一数的左边,则有一花费,反之没要。问需要多少花费能让数列全变成0。
用一个cnt存当前能够使用的正数的和,遇到负数就取出正数与其中和,遇到正数就加上,cnt最小为0。到末尾时输出cnt。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
const ll mod = 1e6 + 1e6+5;
ll INF = 1e18;
ll ans = 0;
int dataa[mod] = {};
int tmpa[mod] = {};
int min(int b, int a) { if (a > b)return b; return a; }
int main()
{
ll n;
cin >> n;
while (n--)
{
ll m;
cin >> m;
for (int i = 0; i < m; i++)scanf("%d", &dataa[i]);
ll pa = 0;
for (int i = 0; i < m; i++) {
if (dataa[i] < 0) {
pa += dataa[i];
if (pa < 0)pa = 0;
}
else pa += dataa[i];
}
cout << pa << '
';
}
}
C. Balanced Bitstring
字符串中,每隔k个的字符应该是相同的,所以我们可以先跑一遍确定前k个的字符,最后确定前k个字符满不满足0和1各一半即可。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
const ll mod = 1e6 + 1e6+5;
ll INF = 1e18;
ll ans = 0;
int dataa[mod] = {};
int tmpa[mod] = {};
int min(int b, int a) { if (a > b)return b; return a; }
int max(int a, int b) { if (a > b)return a; return b;}
string s;
void solve(int m, int k) {
for (int i = 0; i < k; i++) {
for (int j = i; j < s.length(); j += k) {
if (s[j] == '?')continue;
if (s[i] == '?' && s[j] != '?')s[i] = s[j];
else if (s[i] != '?' && s[i] != s[j]) { cout << "NO
"; return; }
}
}
int cnt = 0,ans=0;
for (int i = 0; i < k; i++) {
if (s[i] == '1')ans++;
if (s[i] == '?')cnt++;
}
if (ans <= k / 2 && ans + cnt >= k / 2)cout << "YES
";
else cout << "NO
";
}
int main()
{
ll n;
cin >> n;
while (n--)
{
ll m, k;
cin >> m >> k >> s;
solve(m, k);
}
}
D. Tree Tag
A和B都在树的直径上移动是最优的,因此有以下几种情况
1.A B的距离小于等于da,A直接把B带走
2.db>=2da+1,B可以在A接近后走到A的反向,但是前提是有足够的空间
3.树的直径<2da+1,B没有足够的空间放风筝,因此被带走,反之B获胜
所以我们可以先bfs出ab距离和树的直径,判断下即可
补题的时候数组开小了。。。。。疯狂wa
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include<vector>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
ll ans = 0;
ll k,a,b,da,db;
vector<int> v[200000+5];
int d[200000 + 5];
bool vis[200000 + 5];
int que[200000 + 5];
void bfs(int st) {
memset(d, 0, sizeof(d));
memset(vis, 0, sizeof(vis));
int l = 0, r = -1;
que[++r] = st;
vis[st] = 1;
while (r>=l)
{
int tmp = que[l++];
for (int i = 0; i < v[tmp].size(); i++) {
if (!vis[v[tmp][i]]) {
vis[v[tmp][i]] = 1;
d[v[tmp][i]] = d[tmp] + 1;
que[++r] = v[tmp][i];
}
}
}
}
int main() {
ll n;
cin >> n;
while (n--)
{
cin >> k>>a>>b>>da>>db;
for (int i = 0; i <= k; i++)v[i] = vector<int>();
for (int i = 0; i < k-1; i++) {
int tmp1, tmp2;
cin >> tmp1 >> tmp2;
v[tmp1].push_back(tmp2);
v[tmp2].push_back(tmp1);
}
if (db <= da * 2 ) {
cout << "Alice
";
continue;
}
bfs(a);
if (d[b] <= da) {
cout << "Alice
";
continue;
}
bfs(1);
int u = 0;
for (int i = 0; i <= k; i++)if (d[i] > d[u])u = i;
bfs(u);
int r = 0;
for (int i = 0; i <= k; i++)r = max(r, d[i]);
if (r < 2*da+1) {
cout << "Alice
";
continue;
}
else cout << "Bob
";
}
}