湖南多校第二场
按照个人难度排序,没写的就是不是我写的,指路[队友blog]
I
签到题,忘记了
D
队友写的
B
判断Alice能否获胜只需要折半查找
发现对于n>3的情况Bob不可能能走遍所有格子,Alice至少能平局。(手模可以证明)
所以对于n<=3的情况暴搜即可
H
纯暴力题。。本来想了一个细节做法,就是确定一个点的位置往后面找其他两个点。队友说可以n方预处理两点关系然后 \(n^3\) 统计答案
J
每次只和相邻的飞机有关,所以把序列看为一个链表,每次取权值最小的边和点一起删掉就可以。优先队列+链表+线段树
K
猜结论
F
每次询问的时候对询问点排序然后挨个lca后缀,看能否符合答案
E
dp+数据结构优化
dp思路就是分三种情况,转移点有两维限制,一维是两个字母相等,另一维是出现次数,用数据结构统计即可。
尝试写了一个树状数组+离散化做法,原本写错写成离散化3次,mle了。但是其实要离散化3*n次,此过程中需要多开许多个vector,我觉得非常构式,所以还是建议写线段树吧。
线段树常数比平衡树以及离散化会小一些,但是空间是 \(nlog(n)\) 的
这里有一个点我也不是很懂,就是N要开到1e6+2或者要把MXL设为0,不然就会死循环以至于MLE
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+2, maxn = 1e3 + 7, mod = 998244353;
using i64 = long long;
#define MXL 1
#define MXR 2e6 + 5
#define lowbit(x) (x & (-x))
// #define int long long
int k, n, m, dip[N], dic[N], dpc[N], f[N];
void add(int &x, int y) {
x = 1ll*(x + y > mod) ? (x + y - mod) : (x + y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
struct Tree{
int ls[N*25], rs[N*25], root[N], sum[N*25], tot = 0;
// t[k][num][x] 树状数组存储的是第num种情况,相等值为k,差值为x
void init() {
memset(ls, 0, sizeof(ls));
memset(rs, 0, sizeof(rs));
memset(root, 0, sizeof(root));
memset(sum, 0, sizeof(sum));
tot = 0;
}
int que(int x, int l, int r, int qr) {
// cout << l << r <<' '<<qr<< endl;
if (r <= qr) {
return sum[x];
}
int mid = (l + r) / 2;
int res = 0;
add(res, que(ls[x], l, mid, qr));
if (mid < qr) add(res, que(rs[x], mid + 1, r, qr));
return res;
}
void upd(int &x, int l, int r, int q, int val) {
if (!x) x = ++tot;
add(sum[x], val);
if (l == r) {
return;
}
int mid = (l + r) / 2;
if (q <= mid) upd(ls[x], l, mid, q, val);
else upd(rs[x], mid + 1, r, q, val);
}
}t[3];
void solve() {
string s; cin >> s; s = ' ' + s;
int len = s.size() - 1, mn = N;
vector<int>dc(len + 1, 0), di(len + 1, 0), dp(len + 1, 0);
for (int i = 0; i < 3; i++) t[i].init();
//IP
dc[0] = di[0] = dp[0] = N;
for (int i = 1; i <= len; i++) {
dip[i] = dip[i - 1];
dc[i] = dc[i - 1];
if (s[i] == 'I') dip[i]++, dc[i]--;
else if (s[i] == 'P') dip[i]--;
else dc[i]++;
mn = min(mn, dip[i]);
}
if (mn <= 0) {
mn = -mn + 1;
for (int i = 0; i <= len; i++) dip[i] += mn;
}
//IC
mn = N;
for (int i = 1; i <= len; i++) {
dic[i] = dic[i - 1];
dp[i] = dp[i - 1];
if (s[i] == 'I') dic[i]++, dp[i]--;
else if (s[i] == 'C') dic[i]--;
else dp[i]++;
mn = min(mn, dic[i]);
}
if (mn <= 0) {
mn = -mn + 1;
for (int i = 0; i <= len; i++) dic[i] += mn;
}
//PC
mn = N;
for (int i = 1; i <= len; i++) {
dpc[i] = dpc[i - 1];
di[i] = di[i - 1];
if (s[i] == 'C') dpc[i]++, di[i]--;
else if (s[i] == 'P') dpc[i]--;
else di[i]++;
mn = min(mn, dpc[i]);
}
if (mn <= 0) {
mn = -mn + 1;
for (int i = 0; i <= len; i++) dpc[i] += mn;
}
//cnt
t[0].upd(t[0].root[dip[0]], MXL, MXR, dc[0], 1);
t[1].upd(t[1].root[dic[0]], MXL, MXR, dp[0], 1);
t[2].upd(t[2].root[dpc[0]], MXL, MXR, di[0], 1);
// cout << "dc "<<dc[0] <<" dp "<<dp[0]<<" di "<<di[0] << endl;
// cout << "dip "<<dip[0] <<" dic "<<dic[0]<<" dpc "<<dpc[0] << endl;
// cout << "X? "<<endl;
for (int i = 1; i <= len; i++) {
// cout << i << endl;
// cout << "dc "<<dc[i] <<" dp "<<dp[i]<<" di "<<di[i] << endl;
// cout << "dip "<<dip[i] <<" dic "<<dic[i]<<" dpc "<<dpc[i] << endl;
add(f[i], t[0].que(t[0].root[dip[i]], MXL, MXR, dc[i] - 1));
add(f[i], t[1].que(t[1].root[dic[i]], MXL, MXR, dp[i] - 1));
add(f[i], t[2].que(t[2].root[dpc[i]], MXL, MXR, di[i] - 1));
t[0].upd(t[0].root[dip[i]], MXL, MXR, dc[i], f[i]);
t[1].upd(t[1].root[dic[i]], MXL, MXR, dp[i], f[i]);
t[2].upd(t[2].root[dpc[i]], MXL, MXR, di[i], f[i]);
// cout << f[i] << endl;
}
cout << f[len] << endl;
}
signed main() {
ios::sync_with_stdio(false);
int t = 1;
// cin >> t;
while(t--) solve();
}
A
我不会

浙公网安备 33010602011771号