最近做需求太无聊了,7、8 双月如果不太忙的话,codeforces冲波分,补一下最近div2的题找找状态
题意
给你n个0和m个1,构造一个字符串,定义字符串的价值为它的所有前缀字符串中0的数量和1的数量的差值的最大值,构造价值最小的串
做法
可以发现最最小价值就是二者数量的差值,交叉防止0和1即可
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
int main() {
int T;
sc("%d", &T);
while (T--)
{
int n, m;
sc("%d%d", &n, &m);
if (n < m) {
for (int i = 0; i < n; i++)
pr("01");
for (int i = n; i < m; i++)
pr("1");
}
else
{
for (int i = 0; i < m; i++)
pr("01");
for (int i = m; i < n; i++)
pr("0");
}
pr("\n");
}
}
题意
给你一个长度为n的字符串,每次操作你可以将其中的01变成1,10变成0,对于这个字符串的所有子串,在不限制操作次数的前提下,可以将多少个子串的长度变成1
做法
对于一个字符串而言,若干次操作后,只会保留同一个字母的后缀,那么我们只需要确保最后两位是不同的,那么前缀无论如果都可以消除
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
char s[200005];
int main() {
int T;
sc("%d", &T);
while (T--)
{
int len;
sc("%d%s", &len, s + 1);
ll ans = 0, pre0 = 0, pre1 = 0;
for (int i = 1; i <= len; i++) {
if (i == 1 || s[i] != s[i - 1]) {
ans += i;
}
else
ans++;
}
pr("%lld\n", ans);
}
}
题意
有一个长度为n的数组,初始值都为0,有一个指针位于第一个元素上,有两种操作
最后,指针必须仍然位于第一个元素上
给你一个长度为n的数组a,问能否通过一些操作将初始值都为0的数字变成数组a
做法
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
ll a[200005];
int main() {
int T;
sc("%d", &T);
while (T--)
{
int n;
sc("%d", &n);
ll pre = 0;
for (int i = 1; i <= n; i++)
sc("%lld", &a[i]);
for (int i = 1; i <= n; i++)
{
pre += a[i];
if (pre < 0) {
pr("NO\n");
goto qwe;
}
if (pre == 0) {
for (int j = i + 1; j <= n; j++) {
if (a[j] != 0) {
pr("NO\n");
goto qwe;
}
}
pr("YES\n");
goto qwe;
}
}
if (pre == 0)
pr("YES\n");
else
pr("NO\n");
qwe:;
}
}
题意
有一颗根节点为1的树,初始时每个节点的值都是0,每次操作可以选择以1号节点开始的链(假设链上的节点为
b
1
,
b
2
,
.
.
.
,
b
k
b_1, b_2, ..., b_k
b1,b2,...,bk),并且为链上的节点的值增加
c
1
,
c
2
,
.
.
.
,
c
k
c_1, c_2, ..., c_k
c1,c2,...,ck(其中数组C需要满足
0
≤
c
1
≤
c
2
≤
.
.
.
≤
c
k
0 \leq c_1 \leq c_2 \leq ... \leq c_{k}
0≤c1≤c2≤...≤ck),要求最终每个节点
i
i
i 的值需要满足
l
i
≤
a
i
≤
r
i
l_i \leq a_i \leq r_i
li≤ai≤ri
问至少需要进行多少次操作可以让所有节点的值都满足上述条件
做法
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
int fa[200005];
int in[200005];
ll val[200005];
ll l[200005];
ll r[200005];
int main() {
int T;
sc("%d", &T);
while (T--)
{
int n;
sc("%d", &n);
for (int i = 1; i <= n; i++)
val[i] = 0;
for (int i = 2; i <= n; i++) {
int t = 0;
sc("%d", &t);
fa[i] = t;
in[t]++;
}
for (int i = 1; i <= n; i++)
sc("%lld%lld", &l[i], &r[i]);
ll ans = 0;
queue<int>q;
for (int i = 1; i <= n; i++)
if (in[i] == 0) {
ans++;
val[i] = r[i];
q.push(i);
}
while (!q.empty()) {
int u = q.front();
q.pop();
val[fa[u]] += val[u];
in[fa[u]]--;
if (in[fa[u]] == 0) {
if (val[fa[u]] < l[fa[u]]) {
ans++;
val[fa[u]] = r[fa[u]];
}
else {
val[fa[u]] = min(r[fa[u]], val[fa[u]]);
}
q.push(fa[u]);
}
}
pr("%lld\n", ans);
}
}
题意
给你n个点,m条边的有向图,你需要从1号节点走到n号节点,每次操作你可以选择删掉一条路,或者随机选择一条路并通过这条路到达下一个节点,求确保你能到达n号节点的最小操作数量
保证至少存在一条道路从1号节点出发,并到达n号节点
做法
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
const int MAXN = 2e5 + 5;
struct edge {
int to;
int nex;
}e[MAXN * 2];
int head[MAXN], tot;
void init() {
memset(head, -1, sizeof head);
tot = 1;
}
void add(int a, int b) {
e[tot] = { b,head[a] };
head[a] = tot++;
}
ll dis[MAXN];
ll cnt[MAXN];
bool vis[MAXN];
#define Pair pair<ll, int>
int main() {
init();
int n, m;
sc("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
dis[i] = 1e18;
while (m--) {
int a, b;
sc("%d%d", &a, &b);
add(b, a);
cnt[a]++;
}
auto dij = [&](int st) {
priority_queue<Pair, vector<Pair>, greater<Pair>>q;
q.push(Pair{ 0,st });
dis[st] = 0;
while (!q.empty()) {
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int i = head[u]; i + 1; i = e[i].nex) {
int to = e[i].to;
dis[to] = min(dis[to], dis[u] + cnt[to]);
q.push(Pair{ dis[to], to });
cnt[to]--;
}
}
};
dij(n);
pr("%lld\n", dis[1]);
}