gym 南京站
I
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int vis[1000];
void solve()
{
string str;
cin >> str;
int ans = 0;
memset(vis, 0, sizeof vis);
str = 's' + str;
for (int i = 1; i <str.size(); i++)
{
vis[str[i] - 'a'+1]++;
ans = max(ans, vis[str[i] - 'a'+1]);
}
cout << str.size()-ans-1 << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
G
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int N = 1e6 + 10;
int arr[N];
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
void solve()
{
int n;
scanf("%d",&n);
int sum = 1, cnt = 1;
stack<int> q1;
stack<int> q0;
int cnt1 = 0, cnt0 = 0;
bool flag = 1;
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
if (arr[i] == 1)
{
q1.push(i);
sum++;
cnt++;
}
else if (arr[i]==0)
{
q0.push(i);
}
else
{
if (q1.size())
{
auto t = q1.top();
q1.pop();
cnt--;
arr[t] = -2;
arr[i] = -2;
}
else if (q0.size())
{
auto t = q0.top();
q0.pop();
sum++;
arr[t] = arr[i] = -2;
}
else
{
flag = 0;
}
}
}
if (!flag)
{
puts("-1");
return;
}
for (int i = 1; i <= n; i++)
{
if (arr[i] == -2) continue;
else if (arr[i] == 1)
{
cnt1++;
}
else if (arr[i] == 0)
{
if (cnt1)
{
cnt--;
cnt1--;
continue;
}
else
{
cnt0++;
}
}
}
int t = cnt0;
sum += t / 2 + t % 2;
cnt += t % 2;
int aa = gcd(sum, cnt);
sum /= aa;
cnt /= aa;
printf("%d %d\n", sum, cnt);
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
solve();
}
}
A
题意:
给出一个n*m的矩阵,矩阵中的袋鼠整体按照操作序列行动,问多少个位置为洞的时剩下的袋鼠的数量刚好为k
思路:
首先可以发现把移动过程逆过来后,可以转变成边界的移动,不在边界里面的袋鼠就掉下去了,即:
U(上边界与下边界向下移动)
D(上边界与下边界向上移动)
L (左边界与右边界向右移动)
R (左边界与右边界向左移动)
移动完后剩下的袋鼠我们可以用(D-L+1)*(R-L+1)来表示数量
其次如果边界U>D或者L>R需要特判,此情况没有袋鼠存留
还剩下一个问题就是洞的选取,我们可以把两个情况分开,分成两张图,一张是袋鼠存活情况的图,这个图是不变的,还有一个是洞的移动轨迹图(采用逆向移动)
暴力想法应该是袋鼠的图不动,遍历洞的位置计算答案,但是因为洞的轨迹图是完全一样的,我们可以反过来洞的轨迹图不动,根据袋鼠图与洞的相对位置,利用前缀和求解答案。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e3 + 10, M = 1e3 + 10;
int f[N * 2 + 10][M * 2 + 10];
void solve()
{
int n, m, k;
cin >> n >> m >> k;
string str;
cin >> str;
str = 's' + str;
int U = 1, D = n, L = 1, R = m;
int u = U, d = D, l = L, r = R;
for (int i = 1; i < str.size(); i++)
{
if (str[i] == 'U')
u++, d++;
else if (str[i] == 'D')
u--, d--;
else if (str[i] == 'L')
l++, r++;
else if (str[i] == 'R')
l--, r--;
U = max(U, u);
D = min(D, d);
L = max(L, l);
R = min(R, r);
}
if (U > D || L > R)
{
if (k == 0) cout << n * m << endl;
else puts("0");
return;
}
int last = (D - U + 1) * (R - L + 1) - k;
if (last < 0)
{
puts("0");
return;
}
//默认初始洞的位置在(1,1)
for (int i = 1; i <= n * 2 + 10; i++)
for (int j = 1; j <= m * 2 + 10; j++) f[i][j] = 0;
int poi = n + 1, poj = m + 1;
int x = poi, y = poj;
f[poi][poj] = 1;
r = poi, l = poj;
for (int i = 1; i < str.size(); i++)
{
if (str[i] == 'U') r++;
if (str[i] == 'D') r--;
if (str[i] == 'L') l++;
if (str[i] == 'R')l--;
f[r][l] = 1;
}
for (int i = 1; i <= n * 2 + 10; i++)
{
for (int j = 1; j <= m * 2 + 10; j++)
{
f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
x = poi - i, y = poj - j;
int d = f[D + x][R + y] - f[U + x - 1][R + y] - f[D + x][L + y - 1] + f[U + x - 1][L + y - 1];
if (d == last) ans++;
}
}
cout << ans << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}