A. Three Piles of Candies
http://codeforces.com/contest/1196/problem/A
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
ll a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
printf("%lld\n", (a + b + c) / 2);
}
}
B. Odd Sum Segments
http://codeforces.com/contest/1196/problem/B
将n个数分为k块,每块是奇数个,可以分的话输出每个区间的右端点
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[200005];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int cnt = 0;
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
if (a[i] & 1)
{
a[i] = 1;
cnt++;
}
else
a[i] = 0;
}
if (cnt < k)
{
printf("NO\n");
continue;
}
int he = cnt - k;
if (he & 1)
{
printf("NO\n");
continue;
}
vector<int>v;
for (int i = 1; i <= n; i++)
{
if (a[i] == 1)
{
if (he >= 0)
he--;
else
v.push_back(i - 1);
}
}
v.push_back(n);
int len = v.size();
printf("YES\n");
for (int i = 0; i < len; i++)
printf("%d%c", v[i], i == len - 1 ? '\n' : ' ');
}
}
C. Robot Breakout
http://codeforces.com/contest/1196/problem/C
有n个机器人,他们有些不能向某个方向移动,问能否交于一点,可以输出一个交点。
遍历每个机器人来维护四个顶点。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int xs[200005], ys[200005];
int a1[200005], b1[200005], c1[200005], d1[200005];
int main()
{
int T, n;
int x, y;
int a, b, c, d;
scanf("%d", &T);
while (T--)
{
int xl = -100000, xr = 100000, yd = -100000, yu = 100000;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d%d%d%d%d%d", &xs[i], &ys[i], &a1[i], &b1[i], &c1[i], &d1[i]);
for (int i = 1; i <= n; ++i)
{
x = xs[i], y = ys[i], a = a1[i], b = b1[i], c = c1[i], d = d1[i];
if (a == 0 && c == 0)
{
if (xl > x || xr < x)
{
printf("0\n");
goto qwe;
}
else xl = xr = x;
}
else if (a == 0 && c == 1)
{
if (xr < x)
{
printf("0\n");
goto qwe;
}
else
xl = max(xl, x);
}
else if (a == 1 && c == 0)
{
if (xl > x)
{
printf("0\n");
goto qwe;
}
else
xr = min(xr, x);
}
if (b == 0 && d == 0)
{
if (yu<y || yd>y)
{
printf("0\n");
goto qwe;
}
else
yu = yd = y;
}
else if (b == 0 && d == 1)
{
if (yd > y)
{
printf("0\n");
goto qwe;
}
else
yu = min(yu, y);
}
else if (b == 1 && d == 0)
{
if (yu < y)
{
printf("0\n");
goto qwe;
}
else
yd = max(yd, y);
}
}
printf("1 %d %d\n", xl, yu);
qwe:;
}
}
D1. RGB Substring (easy version)
D2. RGB Substring (hard version)
http://codeforces.com/contest/1196/problem/D2
要使长度为 n 的只包含 R G B 的序列中,出现长度为k的 RGBRGBRGB……的子串(连续)的最小代价,其中改变一个字母的代价为1.
首先预处理当起点为R G B 是各个点的维护代价
然后求一个前缀
然后遍历整个序列,求一下以当前为起点,所需要的代价是多少。
#include <bits/stdc++.h>
using namespace std;
char s[200005];
int a[3][200005];
int sum[3][200005];
char type[3] = { 'R','G','B' };
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n, k;
scanf("%d%d", &n, &k);
scanf("%s", s + 1);
int len = strlen(s + 1);
for (int i = 0; i < 3; i++)
{
for (int j = 1; j < len + 1; j++)
{
if (s[j] == type[(i + j) % 3])
a[i][j] = 0;
else
a[i][j] = 1;
sum[i][j] = sum[i][j - 1] + a[i][j];
}
}
int minn = 200005;
for (int i = 0; i < 3; i++)
{
for (int j = 1; j < len + 1; j++)
{
if (j + k - 1 >= len + 1)
continue;
minn = min(minn, sum[i][j + k - 1] - sum[i][j - 1]);
}
}
printf("%d\n", minn);
}
}
E. Connected Component on a Chessboard
http://codeforces.com/contest/1196/problem/E
有一个棋盘,长度1e9*1e9,(1,1)方格是白色,然后黑白相间,问你能否找到一个联通块使得出现过b次黑色,w次白色。
只有当两个方块中间存在一条公共边时,我们认为他联通。
1、首先,假设a个白色,最多只能3*a+1个黑色,所以我们可以判掉不合法情况
2、然后我们先取一个数量大的颜色,然后将所有数量少的颜色相邻取第一个取的颜色后。
3、此时颜色少的个数为0,颜色多的取在我们已经练成的线的颜色少方格的上下一个单位。
4、具体实现看代码
#include <bits/stdc++.h>
using namespace std;
void print(int x, int y)
{
printf("%d %d\n", x, y);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int b, w;
scanf("%d%d", &b, &w);
if (b < w)
{
if (w > 3 * b + 1)
{
printf("NO\n");
continue;
}
printf("YES\n");
int sx = 2, sy = 4;//白
int x = 2, y = 4;
print(x, y);
w--;
while (b != 0)
{
y++;
print(x, y);
y++;
print(x, y);
b--;
w--;
}
for (int i = sy + 1; i <= y; i += 2)
{
if (w)
{
print(x - 1, i);
w--;
}
else
break;
if (w)
{
print(x + 1, i);
w--;
}
else
break;
}
}
else if (b > w)
{
if (b > 3 * w + 1)
{
printf("NO\n");
continue;
}
printf("YES\n");
int sx = 2, sy = 3;//黑
b--;
int x = 2, y = 3;
print(x, y);
while (w != 0)
{
y++;
print(x, y);
y++;
print(x, y);
b--;
w--;
}
for (int i = sy + 1; i <= y; i += 2)
{
if (b)
{
print(x - 1, i);
b--;
}
else
break;
if (b)
{
print(x + 1, i);
b--;
}
else
break;
}
}
else
{
int x = 3, y = 3;
printf("YES\n");
while (b)
{
y++;
print(x, y);
y++;
print(x, y);
b--;
}
}
}
}
F. K-th Path
http://codeforces.com/contest/1196/problem/F
没有起点终点,要求第k短路
由于K小于400,最多取400条边,800个点,先离散化一下,然后跑Floyd。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
int u;
int v;
ll w;
}in[400000];
ll dis[1000][1000];
void flody(int n)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
if (dis[j][k] > dis[j][i] + dis[i][k])
dis[j][k] = dis[j][i] + dis[i][k];
}
#define Pair pair<int,int>
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= 1001; i++)
for (int j = 1; j <= 1001; j++)
if (i == j)
dis[i][j] = 0;
else
dis[i][j] = 1e18 + 7;
for (int i = 1; i <= m; i++)
scanf("%d%d%lld", &in[i].u, &in[i].v, &in[i].w);
sort(in + 1, in + m + 1, [](node q, node w) {
return q.w < w.w;
});
//离散化
vector<int>dot;
for (int i = 1; i <= min(m, k); i++)
{
dot.push_back(in[i].u);
dot.push_back(in[i].v);
}
sort(dot.begin(), dot.end());
dot.erase(unique(dot.begin(), dot.end()), dot.end());
int len = dot.size();
//加边
for (int i = 1; i <= min(m, k); i++)
{
in[i].u = lower_bound(dot.begin(), dot.end(), in[i].u) - dot.begin() + 1;
in[i].v = lower_bound(dot.begin(), dot.end(), in[i].v) - dot.begin() + 1;
dis[in[i].u][in[i].v] = in[i].w;
dis[in[i].v][in[i].u] = in[i].w;
}
flody(len);
vector<ll>v;
for (int i = 1; i <= len; i++)
{
for (int j = i + 1; j <= len; j++)
v.push_back(dis[i][j]);
}
sort(v.begin(), v.end());
printf("%lld\n", v[k - 1]);
}