AtCoder Beginner Contest 342 A-G
A
void solve()
{
string s, s1;
cin >> s;
s1 = s;
sort(s1.begin(), s1.end());
char ans;
if (s1[0] == s1[1])
ans = s1.back();
else
ans = s1[0];
for (int i = 0; i < s.size(); i++)
if (s[i] == ans)
{
cout << i + 1 << endl;
return;
}
}
B
void solve()
{
int n;
cin >> n;
map<int, int> mp;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
mp[x] = i;
}
int q;
cin >> q;
for (int i = 1; i <= q; i++)
{
int a, b;
cin >> a >> b;
cout << (mp[a] > mp[b] ? b : a) << endl;
}
}
C
暴力合并即可
void solve()
{
vector<vector<int>> a(100);
int n, q;
string s;
cin >> n;
cin >> s;
for (int i = 0; i < s.size(); i++)
a[(s[i] - 'a')].push_back(i);
cin >> q;
for (int i = 1; i <= q; i++)
{
char u, v;
cin >> u >> v;
int x = u - 'a', y = v - 'a';
if (x == y)
continue;
if (a[x].empty())
continue;
else
{
if (a[y].size())
{
for (auto e : a[x])
a[y].push_back(e);
a[x].clear();
}
else
swap(a[x], a[y]);
}
}
vector<char> ans(n + 1, '#');
for (int i = 0; i < 26; i++)
{
for (auto p : a[i])
ans[p] = char('a' + i);
}
for (int i = 0; i < n; i++)
cout << ans[i];
}
D
答案只有以下几种情况:
假设0既不是平方数,也不是非平凡数
1.平方数*平方数
2.非平方数*非平方数
3.0*非零
4.非零*0
1.3.4可以直接计数,接下来考虑怎么算2对答案的贡献
考虑平方数的性质,每个质因子的指数都是偶数,所以两个非平方数相乘也要满足
记录一下非平方数中指数是奇数的数的乘积,这个乘积是唯一的,用map计数即可
void solve()
{
auto getpr = [&](int n)
{
vector<bool> not_pr(n + 10, 0);
for (int i = 2; i <= n; ++i)
{
if (!not_pr[i])
pr.push_back(i);
for (int p : pr)
{
if (i * p > n)
break;
not_pr[i * p] = true;
if (i % p == 0) // 说明i*p已经被一个更小的i判断过了
break;
}
}
};
getpr(450);
ll n, cnt = 0, ans = 0, zero = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
ll x;
cin >> x;
if (!x)
{
ans += i - 1;
zero++;
continue;
}
ans += zero;
ll fac = 1;
auto chk = [&]() -> void
{
for (auto p : pr)
{
if (p > x)
break;
if (x % p == 0)
{
ll num = 0;
while (x % p == 0)
x /= p, num++;
if (num & 1)
fac *= p;
}
}
if (x > 1)
fac *= x;
};
chk();
ans += mp[fac];
mp[fac]++;
}
cout << ans << endl;
}
E
建反图跑最短路
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<array<ll, 5>>> e(n + 1);
for (int i = 1; i <= m; i++)
{
ll l, d, k, c, a, b;
cin >> l >> d >> k >> c >> a >> b;
e[b].push_back({l, d, k, c, a});
}
priority_queue<pll> pq;
vector<ll> dis(n + 1, -1);
vector<bool> vis(n + 1, 0);
dis[n] = 2e18;
pq.push({dis[n], n});
while (pq.size())
{
auto [dist, u] = pq.top();
pq.pop();
if (vis[u])
continue;
vis[u] = 1;
for (auto [l, d, k, c, a] : e[u])
{
ll lst = (dis[u] - l - c) / d;
lst = min(lst, k - 1);
if (l + lst * d > dis[a])
{
dis[a] = l + lst * d;
pq.push({dis[a], a});
}
}
}
for (int i = 1; i < n; i++)
if (dis[i] == -1)
cout << "Unreachable" << endl;
else
cout << dis[i] << endl;
}
F
概率dp
f[i]表示点数为i是,采取最优策略的获胜概率
每个当前位置有两种情况:
掷色子,\(f[i]=\sum_{j=i+1}^{i+d}f[j]\)
不掷骰子,\(loss(i)\)表示点数为i时,获胜的概率
这个dp明显要倒着处理
#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 = 1e6 + 100, M = 2;
random_device rd;
mt19937_64 gen(rd());
struct BIT
{
int n;
vector<db> a;
BIT(int _n) : n(_n), a(n + 10) {}
int lb(int x) { return x & -x; }
void add(int x, db y)
{
x++;
for (; x <= n; x += lb(x))
a[x] += y;
}
void modify(int l, int r, db x)
{
add(l, x);
add(r + 1, -x);
}
db query(int x)
{
x++;
db res = 0.;
for (; x; x ^= lb(x))
res += a[x];
return res;
}
};
void solve()
{
int n, l, d;
cin >> n >> l >> d;
vector<db> g(2 * n + 10, 0.), f(2 * n + 10, 0.);
auto lose = [&](int x) -> db
{
if (x > n)
return 0.;
db res = 1 - g[n];
if (x > l)
res += g[x - 1];
return res;
};
auto cal_g = [&]() -> void
{
BIT bit(2 * n);
bit.modify(0, 0, 1.0);
for (int i = 0; i <= 2 * n; i++)
{
g[i] = bit.query(i);
if (i < l)
{
bit.modify(i + 1, i + d, g[i] / d);
g[i] = 0;
}
}
for (int i = 1; i <= 2 * n; i++)
g[i] += g[i - 1];
};
auto cal_f = [&]() -> void
{
db sum = 0;
for (int i = 2 * n; i >= 0; i--)
{
if (i > n)
f[i] = 0;
else
{
f[i] = max(sum / d, lose(i));
}
sum += f[i];
if (i + d <= 2 * n)
sum -= f[i + d];
}
};
cal_g();
cal_f();
cout << f[0] << endl;
}
int main()
{
cout << setprecision(10);
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int _ = 1;
// cin >> _;
while (_--)
solve();
return 0;
}
G
建一棵以mulitset作为节点的线段树
操作1就是对节点打标记(不下传)
操作2就是删除标记(暴力删)
操作3从叶子往上走,不断取max即可
struct segtree
{
int n;
vector<multiset<int>> a;
vector<int> leaf;
segtree(int _n) : n(_n * 4 + 10), a(n + 1), leaf(_n + 10) {}
void build(int id, int l, int r)
{
if (l == r)
leaf[l] = id;
else
{
int mid = l + r >> 1;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
}
}
void modify(int id, int l, int r, int ql, int qr, int t)
{
if (r < ql || l > qr)
return;
if (l >= ql && r <= qr)
{
if (t > 0)
a[id].insert(t);
else
a[id].extract(-t);
return;
}
int mid = l + r >> 1;
if (ql <= mid)
modify(id * 2, l, mid, ql, qr, t);
if (qr > mid)
modify(id * 2 + 1, mid + 1, r, ql, qr, t);
}
ll query(int x)
{
int id = leaf[x];
int ans = 0;
while (id > 0)
{
if (a[id].size())
ans = max(ans, *a[id].rbegin());
id /= 2;
}
return ans;
}
};
void solve()
{
int n, q;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
cin >> q;
segtree seg(n);
seg.build(1, 1, n);
int opt, l, r, x;
vector<array<int, 3>> op(q + 1);
for (int i = 1; i <= q; i++)
{
cin >> opt;
if (opt == 1)
{
cin >> l >> r >> x;
seg.modify(1, 1, n, l, r, x);
op[i] = {l, r, x};
}
else if (opt == 2)
{
cin >> x;
auto [l, r, t] = op[x];
seg.modify(1, 1, n, l, r, -t);
}
else
{
cin >> x;
cout << max(a[x], seg.query(x)) << endl;
}
}
}
进一步优化时间,可以将mulitset优化成一个带修堆
struct segtree
{
struct heap
{
priority_queue<int> p, q;
void push(int x)
{
p.push(x);
}
int top()
{
while (p.size() && q.size() && p.top() == q.top())
p.pop(), q.pop();
if (p.size())
return p.top();
return -1;
}
void del(int x)
{
q.push(x);
}
};
int n;
vector<heap> a;
vector<int> leaf;
segtree(int _n) : n(_n * 4 + 10), a(n + 1), leaf(_n + 10) {}
void build(int id, int l, int r)
{
if (l == r)
leaf[l] = id;
else
{
int mid = l + r >> 1;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
}
}
void modify(int id, int l, int r, int ql, int qr, int t)
{
if (r < ql || l > qr)
return;
if (l >= ql && r <= qr)
{
if (t > 0)
a[id].push(t);
else
a[id].del(-t);
return;
}
int mid = l + r >> 1;
if (ql <= mid)
modify(id * 2, l, mid, ql, qr, t);
if (qr > mid)
modify(id * 2 + 1, mid + 1, r, ql, qr, t);
}
ll query(int x)
{
int id = leaf[x];
int ans = 0;
while (id > 0)
{
ans = max(ans, a[id].top());
id /= 2;
}
return ans;
}
};
void solve()
{
int n, q;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
cin >> q;
segtree seg(n);
seg.build(1, 1, n);
int opt, l, r, x;
vector<array<int, 3>> op(q + 1);
for (int i = 1; i <= q; i++)
{
cin >> opt;
if (opt == 1)
{
cin >> l >> r >> x;
seg.modify(1, 1, n, l, r, x);
op[i] = {l, r, x};
}
else if (opt == 2)
{
cin >> x;
auto [l, r, t] = op[x];
seg.modify(1, 1, n, l, r, -t);
}
else
{
cin >> x;
cout << max(a[x], seg.query(x)) << endl;
}
}
}