链接:
A:Alice's Adventures in ''Chess''
大意:
在二维坐标上循环移动能否到某一点
思路:
数据范围很小,多循环几次,
最少21次,题解说的,不太确定,循环1000次都行,反正别循环10就行了
代码:
#include <bits/stdc++.h>
#include <array>
using namespace std;
#define int long long
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define vii vector<pair<int, int>>
#define ff first
#define ss second
// ++ ~! */+- <<>> <> == &^| &&|| =
void solve()
{
int n, a, b;cin >> n >> a >> b;
string s;cin >> s;
map<char, pair<int, int>> dir;
dir['N'] = { 0, 1 };
dir['E'] = { 1, 0 };
dir['S'] = { 0, -1 };
dir['W'] = { -1, 0 };
int x = 0, y = 0;
int t = 100;
while (t--)
{
for (int i = 0; i < n; i++)
{
int r = x + dir[s[i]].ff, c = y + dir[s[i]].ss;
if (r == a && c == b)
{
cout << "Yes" << endl;
return;
}
x = r, y = c;
}
}
cout << "No" << endl;
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
/* /\_/\
* (= ._.)
* / > \>
*/
B:Alice's Adventures in Permuting
大意:
给长度为n的a[i]表达式,每次可把最大的数变成数组的mex值,求需要几次运算
思路:
b等于零的情况下c < n - 2是没结果的,n-1 n-2都是需要n-1次,大于等于n就是n次都换了
b不等于0话a[i]就没重复的,大于n - 1的数的数量就是结果
代码:
#include <bits/stdc++.h>
#include <array>
using namespace std;
#define int long long
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define vii vector<pair<int, int>>
#define ff first
#define ss second
// ++ ~! */+- <<>> <> == &^| &&|| =
void solve()
{
int n, b, c;cin >> n >> b >> c;
if (b == 0)
{
if (c < n - 2)cout << -1 << endl;
else if (c == n - 2)cout << n - 1 << endl;
else if (c == n - 1)cout << n - 1 << endl;
else cout << n << endl;
return;
}
if (c > n - 1)cout << n << endl;
else
{
int num = (n - 1 - c) / b + 1; // 在0,n - 1范围内的数
cout << n - num << endl;
}
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
/* /\_/\
* (= ._.)
* / > \>
*/
C:Alice's Adventures in Cutting Cake
大意:
一个数组,分成m + 1个区间,使得有m个区间大于给定值的数,求在这种情况下得到的剩下的数的最大值
思路:
由于是连续的,对于要获得的区间,左边和右边一定是按照区间和大于v就分段的,
在这种情况下,从前往后、从后往前分别求最小的第i个大于v的区间端点,然后前后结合一下,左边右边加起来等于m,那么中间就是最优结果
代码:
#include <bits/stdc++.h>
#include <array>
using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define vii vector<pair<int, int>>
#define ff first
#define ss second
// ++ ~! */+- <<>> <> == &^| &&|| =
int n, m, v, s[N], pf[N], sf[N];
void solve() {
cin >> n >> m >> v;
for (int i = 1;i <= n;i++)
{
cin >> s[i];
s[i] += s[i - 1];
}
int s1 = 0, s2 = 0;
for (int i = 1, lst = 0;i <= n; i ++)
if (s[i] - s[lst] >= v)pf[++s1] = lst = i; // 找前缀第s1个v所在位置
sf[0] = n + 1;
for (int i = n, lst = n + 1;i >= 1; i --) // 找后缀第s2个v所在位置
if (s[lst - 1] - s[i - 1] >= v)sf[++s2] = lst = i;
if (s1 < m)
{
cout << -1 << endl;
return;
}
int ans = -1;
for (int i = 0; i <= m; i++)
if (pf[i] < sf[m - i])ans = max(ans, s[sf[m - i] - 1] - s[pf[i]]);
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
/* /\_/\
* (= ._.)
* / > \>
*/
D:Alice's Adventures in Cards
大意:
Alice跟三个人换牌,自己有一张1,其他人1-n都有,目标换到n
她的换牌原则是只换比自己手里大的
其他三人只换权重大的,即a[i]>a[j],可以用j换j
思路:
从后往前找合法转移状态,i可以换n,j可以换i,k可以换j......就这样去往下找到1,记下往后的地址,如果1没有,就输出no,要不就输出结果
从提交里翻出来的代码,官方的总是看着不太好,民间的代码太长也不想看,太短又看不懂
代码:
#include <bits/stdc++.h>
#include <array>
using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define vii vector<pair<int, int>>
#define ff first
#define ss second
// ++ ~! */+- <<>> <> == &^| &&|| =
int a[3][N];
char s[] = "qkj";
int n;
void solve()
{
cin >> n;
for (int i = 0; i < 3; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
int lst[] = {n, n, n}; // 倒着推转移状态,这里的值是表示合法转状态里权值最小的位置,这样会更容易被换
vii trans(n + 1, {0, -1});
for (int i = n - 1; i > 0; i--)
{
int tmp = -1;
for (int j = 0; j < 3; j ++) // 看能否用i从三人那往后换
if (a[j][i] > a[j][lst[j]])
tmp = j; //随便找个合法的就行
if (tmp == -1)continue; // 没找到合法的,那么i不是好状态
trans[i] = { tmp, lst[tmp] }; // 表示i可以与tmp换,换成lst[tmp]
// 更新lst,现在i是合法转移状态,lst[j]也是合法转移状态,当然是权值最小的最好获得,所以要更新一下
for (int j = 0; j < 3; j++)
if (a[j][i] < a[j][lst[j]])lst[j] = i;
}
// 从n往下会有很多叉路,但从1到n的路就一条,这就是树
if (trans[1].second == -1)
{
cout << "NO" << endl;
return;
}
cout << "YES" << endl;
auto t = trans[1];
vector <pair< char, int >> ans;
while (1)
{
ans.push_back({ s[t.ff], t.ss });
if (t.ss == n)break;
t = trans[t.ss];
}
cout << ans.size() << endl;
for (auto it : ans)
cout << it.ff << ' ' << it.ss << endl;
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
/* /\_/\
* (= ._.)
* / > \>
*/