AtCoder Beginner Contest 339 A-G
A
模拟即可
void solve()
{
string s;
cin >> s;
for (int i = s.size() - 1; i >= 0; i--)
if (s[i] == '.')
{
cout << s.substr(i + 1) << endl;
return;
}
}
B
模拟,可以让下标从0开始,这样可以在%n下满足题意
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
void solve()
{
int n, m, opt;
cin >> n >> m >> opt;
vector<vector<char>> a(n, vector<char>(m, '.'));
int d = 0, x = 0, y = 0;
while (opt--)
{
if (a[x][y] == '.')
{
a[x][y] = '#';
d = (d + 1) % 4;
}
else
{
a[x][y] = '.';
d = (d - 1 + 4) % 4;
}
x = (x + dx[d] + n) % n;
y = (y + dy[d] + m) % m;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
cout << a[i][j];
cout << endl;
}
}
C
从后往前吗模拟:
设当前最少有x人
如果是\(a[i]<0\),则在到达该站前至少\(abs(a[i])\)人
如果是\(a[i]>0\),则在到达该站前可以少\(abs(a[i])\)人
最后再顺着模拟一遍得到答案
void solve()
{
ll n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
ll ans = 0;
for (int i = n; i >= 1; i--)
{
if (a[i] > 0)
{
ans -= a[i];
ans = max(0ll, ans);
}
else
ans -= a[i];
}
for (int i = 1; i <= n; i++)
ans += a[i];
cout << ans << endl;
}
D
同时维护两人的坐标,进行bfs
ll dist[70][70][70][70];
int d[4][4] = {{-1, 1, 0, 0}, {0, 0, -1, 1}, {-1, 1, 0, 0}, {0, 0, -1, 1}};
void solve()
{
int n, cnt = 0;
cin >> n;
array<int, 4> st;
vector<vector<char>> a(n + 1, vector<char>(n + 1));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
cin >> a[i][j];
if (a[i][j] == 'P')
st[cnt++] = i, st[cnt++] = j;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
for (int l = 1; l <= n; l++)
dist[i][j][k][l] = 1e9;
auto bfs = [&](array<int, 4> x) -> void
{
queue<array<int, 4>> q;
q.push(x);
dist[x[0]][x[1]][x[2]][x[3]] = 0;
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++) // 方向
{
array<int, 4> tmp;
for (int j = 0; j < 4; j++)
{
tmp[j] = t[j] + d[j][i];
tmp[j] = min(n, tmp[j]);
tmp[j] = max(1, tmp[j]);
}
if (a[tmp[0]][tmp[1]] == '#')
tmp[0] = t[0], tmp[1] = t[1];
if (a[tmp[2]][tmp[3]] == '#')
tmp[2] = t[2], tmp[3] = t[3];
if (dist[tmp[0]][tmp[1]][tmp[2]][tmp[3]] > dist[t[0]][t[1]][t[2]][t[3]] + 1)
{
dist[tmp[0]][tmp[1]][tmp[2]][tmp[3]] = dist[t[0]][t[1]][t[2]][t[3]] + 1;
q.push(tmp);
}
}
}
};
bfs(st);
ll ans = 1e9;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (a[i][j] == '.')
ans = min(ans, dist[i][j][i][j]);
if (ans == 1e9)
ans = -1;
cout << ans << endl;
}
E
线段树优化dp,维护转移范围内的最大值
struct node
{
ll val;
};
struct segtree
{
int n;
vector<node> a;
segtree(int _n) : n(_n * 4 + 10), a(n + 1) {}
void update(int id) { a[id].val = max(a[id * 2].val, a[id * 2 + 1].val); }
void build(int id, int l, int r, vector<int> &arr)
{
if (l == r)
a[id].val = arr[l];
else
{
int mid = l + r >> 1;
build(id * 2, l, mid, arr);
build(id * 2 + 1, mid + 1, r, arr);
update(id);
}
}
void change(int id, int l, int r, int pos, int val)
{
if (l == r) // 叶子节点
a[id].val = val;
else
{
int mid = l + r >> 1;
if (pos <= mid)
change(id * 2, l, mid, pos, val);
else
change(id * 2 + 1, mid + 1, r, pos, val);
update(id);
}
}
ll query(int id, int l, int r, int ql, int qr)
{
if (l == ql && r == qr)
return a[id].val;
int mid = l + r >> 1;
if (qr <= mid)
return query(id * 2, l, mid, ql, qr);
else if (ql > mid)
return query(id * 2 + 1, mid + 1, r, ql, qr);
else
return max(query(id * 2, l, mid, ql, mid), query(id * 2 + 1, mid + 1, r, mid + 1, qr));
}
};
void solve()
{
int n, d;
cin >> n >> d;
vector<int> a(n + 1), rec(N, 0);
for (int i = 1; i <= n; i++)
cin >> a[i];
segtree seg(N);
seg.build(1, 1, n, rec);
for (int i = 1; i <= n; i++)
{
int l = max(1, a[i] - d), r = min((int)5e5, a[i] + d);
int res = seg.query(1, 1, N, l, r) + 1;
int now = max(seg.query(1, 1, N, a[i], a[i]), 1ll);
now = max(now, res);
seg.change(1, 1, N, a[i], now);
}
ll res = 1;
for (int i = 1; i <= n; i++)
res = max(res, seg.query(1, 1, N, a[i], a[i]));
cout << res << endl;
}
F
如果模数够大,够多,那么就可以保证\(a*b=c\)与\(a%mod*b%mod=c%mod\)等效
可以双哈希,三哈希,或者模数开到ll
正经比赛的话,建议还是双哈希(
void solve()
{
map<ll, ll> mp;
int n;
cin >> n;
vector<ll> a(n + 1);
auto cal = [&](string s) -> ll
{
ll res = 0;
for (int i = 0; i < s.size(); i++)
res = (res * 10 + (s[i] - '0')) % mod;
return res;
};
for (int i = 1; i <= n; i++)
{
string s;
cin >> s;
a[i] = cal(s);
mp[a[i]]++;
}
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
ll tmp = __int128_t(a[i]) * a[j] % mod;
ans += mp[tmp];
}
cout << ans << endl;
}
G
主席树模板题
#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define ls(x) (a[x].l)
#define rs(x) (a[x].r)
#define sum(x) a[x].sum
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 1e9 + 7;
const int N = 7e7 + 10, M = 25;
random_device rd;
mt19937_64 gen(rd());
struct node
{
ll sum, l, r;
};
struct segtree
{
int n;
vector<node> a;
segtree(int _n) : n(1) { a.reserve(_n); }
void update(int id)
{
sum(id) = sum(ls(id)) + sum(rs(id));
}
void build(int id, int l, int r)
{
if (l == r)
sum(id) = 0;
else
{
ls(id) = ++n, rs(id) = ++n;
int mid = l + r >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
update(id);
}
}
void change(int pos, int l, int r, int id, int nxt, int val)
{
if (l == r)
{
sum(nxt) = sum(id) + val;
return;
}
ls(nxt) = ls(id), rs(nxt) = rs(id);
int mid = l + r >> 1;
if (pos <= mid)
ls(nxt) = ++n, change(pos, l, mid, ls(id), ls(nxt), val);
else
rs(nxt) = ++n, change(pos, mid + 1, r, rs(id), rs(nxt), val);
update(nxt);
}
ll query(int id, int l, int r, int ql, int qr) // 查询某个版本的区间和
{
if (l == ql && r == qr)
return sum(id);
int mid = l + r >> 1;
if (qr <= mid)
return query(ls(id), l, mid, ql, qr);
else if (ql > mid)
return query(rs(id), mid + 1, r, ql, qr);
else
return query(ls(id), l, mid, ql, mid) + query(rs(id), mid + 1, r, mid + 1, qr);
}
ll query(int id, int nxt, int l, int r, int ql, int qr) // 在id-nxt版本之间查询值域在ql-qr的和
{
if (ql > qr)
return 0;
if (l == ql && r == qr)
return sum(nxt) - sum(id);
int mid = l + r >> 1;
if (qr <= mid)
return query(ls(id), ls(nxt), l, mid, ql, qr);
else if (ql > mid)
return query(rs(id), rs(nxt), mid + 1, r, ql, qr);
else
return query(ls(id), ls(nxt), l, mid, ql, mid) + query(rs(id), rs(nxt), mid + 1, r, mid + 1, qr);
}
};
void solve()
{
ll n, q, mx = 0;
cin >> n;
vector<ll> a(n + 1), b;
for (int i = 1; i <= n; i++)
cin >> a[i], b.push_back(a[i]), mx = max(mx, a[i]);
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
cin >> q;
vector<ll> root(n + 1);
ll pre = 0;
root[0] = 1;
segtree seg(2e7);
seg.build(root[0], 1, n);
for (int i = 1; i <= n; i++)
{
root[i] = ++seg.n;
int pos = (lower_bound(b.begin(), b.end(), a[i]) - b.begin()) + 1;
seg.change(pos, 1, n, root[i - 1], root[i], a[i]);
}
for (int i = 1; i <= q; i++)
{
ll l, r, val;
cin >> l >> r >> val;
l ^= pre, r ^= pre, val ^= pre;
int pos = (upper_bound(b.begin(), b.end(), val) - b.begin());
pre = seg.query(root[l - 1], root[r], 1, n, 1, pos);
cout << pre << endl;
}
}
int main()
{
// cout << setprecision(5);
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int _ = 1;
// cin >> _;
while (_--)
solve();
return 0;
}