水题......现在最后的形式中最多一个 1,其他的全是 0。注意特判原来给的就是 0 的情况就行(我居然还在这上面挂了一发)
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
int n;
string s;
int cnt[2];
inline void solve()
{
cin >> n >> s;
for (auto i : s)
{
cnt[i - '0']++;
}
if (cnt[1] == 0)
return cout << 0, void();
cout << 1;
for (int i = 0; i < cnt[0]; ++i)
cout << 0;
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
B - Lara Croft and the New Game
也是水题,就按照题意分成三个部分来算一下就行。第三部分算一下奇偶即可。
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
ll n, m, k;
inline void solve()
{
cin >> n >> m >> k;
if (k < n)
return cout << k + 1 << " 1" << endl, void();
else if (k < n + m - 1)
return cout << n << " " << k - n + 2, void();
else
{
k -= n + m - 1;
ll hadhang = k / (m - 1);
ll lefthang = k
if (hadhang & 1)
{
cout << n - 1 - hadhang << ' ' << lefthang + 2 << endl;
}
else
{
cout << n - 1 - hadhang << ' ' << m - lefthang << endl;
}
}
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
按照 $l$ 第一关键字从小到大,$r$ 第二关键字从大到小排序即可,这样存在解的充要条件就是存在相邻两条线段,前一条包含后一条。
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
int n;
struct seg
{
int l, r, id;
bool operator<(const seg &x) const
{
if (l < x.l)
return 1;
if (l > x.l)
return 0;
if (r > x.r)
return 1;
return id < x.id;
}
} s[N];
inline void solve()
{
scanf(
for (int i = 1; i <= n; ++i)
{
int l, r;
scanf(
s[i] = {l, r, i};
}
sort(s + 1, s + n + 1);
for (int i = 1; i < n; ++i)
{
if (s[i + 1].l >= s[i].l && s[i + 1].r <= s[i].r)
return printf(
}
puts("-1 -1");
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
这个题就有意思了(
对于一个问题 $(d_1,d_2,...,d_n)$,我们可以先拿出来 $d_1$ 个点,每个点往其他所有 $n-1$ 个点连边,这样就有了 $d_1$ 个度数为 $d_n$ 的点,这些点后面就不会再参与连边了。
现在可以发现,度数为 $d_1$ 和 $d_n$ 的点都已经有了(除了这 $d_1$ 个点之外的点此时的度数都是 $d_1$,有点绕倒是),那么我们只需要构造出 $d_2,d_3,...,d_{n-1}$ 的点了。将这 $d_1$ 个点撤去之后,也就变成了 $d_2-d_1,d_3-d_2,...,d_{n-1}-d_1$,于是就变成了更小的子问题了。
对于这个子问题,只需要 $d_{n-1}-d_1+1$ 个点就行,但是上一层的问题可能还会有多的点剩下,那么这些多的点个数就是 $(d_n -d_1 + 1) -(d_{n-1} - d_1 + 1) = d_n - d_{n-1}$ 个,让这些点后续操作都不参与就是了。
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
int n;
int d[1050];
vector<pii> e;
inline void solve()
{
scanf(
for (int i = 1; i <= n; ++i)
scanf(
int rt = d[n] + 1;
int l = 1, r = n, p = 1;
while (p < rt && l <= r)
{
for (int i = p; i < p + d[l]; ++i)
for (int j = rt; j > i; --j)
e.push_back({i, j});
for (int i = l + 1; i <= r; ++i)
d[i] -= d[l];
p += d[r] - d[r - 1] + d[l];
l++, r--;
}
random_shuffle(vecall(e));
cout << e.size() << endl;
for (auto [u, v] : e)
printf(
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
(这不显然比 D 简单?)
显然所有的 $a$ 操作只操作同一个生物就行。接下来就是枚举操作哪个生物再 $\mathcal{O}(1)$ 判断即可。
设 $w_i$ 表示第 $i$ 个生物的原贡献。对于 $h_i-d_i>0$ 前 $b$ 大的生物,其 $w_i=h_i$,剩下的就是 $w_i=d_i$。对于枚举到的这个生物,如果原本就在前 $b$ 个之内,那么就计算一下新的贡献就行;否则,将原来 $h_i-d_i$ 最小的那个踢出去换成自己即可(如果本来满足的生物数不够 $b$ 的话,就直接用一次就行)。
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
int n, a, b;
ll h[N], d[N], w[N];
ll ans;
bool vis[N];
vector<int> vec;
bool cmp(const int &x, const int &y) { return h[x] - d[x] > h[y] - d[y]; }
inline void solve()
{
scanf(
for (int i = 1; i <= n; ++i)
{
scanf(
w[i] = d[i];
ans += d[i];
if (h[i] > d[i])
vec.push_back(i);
}
if (b == 0)
return cout << ans << '\n', void();
veccmpsort(vec, cmp);
vec.resize(b);
ll mnh = llinf;
for (int i = 0; i < b; ++i)
{
vis[vec[i]] = 1;
ans = ans - d[vec[i]] + h[vec[i]];
w[vec[i]] = h[vec[i]];
}
for (int i = 1; i <= n; ++i)
mnh = min(mnh, w[i]);
ll res = ans;
for (int i = 1; i <= n; ++i)
{
ll tmp = res;
ll he = h[i] * st(a);
if (he > d[i])
{
if (vis[i])
tmp += (-w[i] + he);
else if (b > 0)
tmp += max(0ll, he - (w[vec[b - 1]] - d[vec[b - 1]]) - w[i]);
}
ans = max(ans, tmp);
}
cout << ans << '\n';
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
我还想写下界最小流来着......想了想太麻烦了(
由于每个点的度数是一定的,那么实际上我们只需要决定删除最多的边即可。
设第 $i$ 个点的度数为 $d_i$,那么只需要连一条容量为 $d_i-k$ 的边即可,二分图中间的边就改成有向边,容量为 $1$,这样,有流量的边就意味着这条边被删除了。跑最大流即可。
不过本题要求所有 $k\in[0,mind_i]$ 的答案。反着过来,每次相当于给这些边的容量 +1,再增广,这样可以加快速度。
时间复杂度为 $\mathcal{O}((n+m)^2)$
#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
printf("\n\nTime used:
system("pause");
#endif
}
const int MAXN = 200050, MAXM = 200050, INF = 0x3f3f3f3f;
struct dinic
{
struct Edge
{
int to, nxt, flow;
} e[MAXM];
int head[MAXN], ecnt = -1, dis[MAXN], cur[MAXN];
void add_edge(int u, int v, int f)
{
e[++ecnt] = {v, head[u], f};
head[u] = ecnt;
e[++ecnt] = {u, head[v], 0};
head[v] = ecnt;
}
int n, m, s, t;
bool bfs()
{
memset(dis, 0, sizeof(dis));
queue<int> q;
dis[s] = 1;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = e[i].nxt)
{
int v = e[i].to;
if (!dis[v] && e[i].flow > 0)
{
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
return dis[t];
}
int dfs(int u, int flow)
{
if (u == t)
return flow;
int nowflow = 0;
for (int &i = cur[u]; ~i; i = e[i].nxt)
{
int v = e[i].to;
if (dis[v] == dis[u] + 1 && e[i].flow > 0)
{
int tmp = dfs(v, min(flow, e[i].flow));
e[i].flow -= tmp;
e[i ^ 1].flow += tmp;
flow -= tmp;
nowflow += tmp;
if (!flow)
break;
}
}
return nowflow;
}
int solve(int n, int s, int t)
{
this->s = s, this->t = t, this->n = n;
int ans = 0;
while (bfs())
{
memcpy(cur, head, (n + 5) * sizeof(int));
ans += dfs(s, INF);
}
return ans;
}
void init()
{
ecnt = -1;
memset(head, -1, sizeof(head));
}
} G;
int n1, n2, m, k = inf, ansflow;
int S, T, d[N];
struct edge
{
int x, y, id;
} e[5050];
vector<vector<int>> ans;
void getans()
{
vector<int> vec;
for (int i = 0; i < m; ++i)
if (G.e[i << 1].flow != 0)
vec.push_back(i + 1);
ans.push_back(vec);
}
inline void solve()
{
G.init();
scanf(
S = n1 + n2 + 1, T = S + 1;
for (int i = 0; i < m; ++i)
{
int x, y;
scanf(
e[i] = {x, y, i << 1};
G.add_edge(x, n1 + y, 1);
d[x]++, d[n1 + y]++;
}
for (int i = 1; i <= n1; ++i)
k = min(k, d[i]);
for (int i = 1; i <= n2; ++i)
k = min(k, d[i + n1]);
for (int i = 1; i <= n1; ++i)
G.add_edge(S, i, d[i] - k);
for (int i = 1; i <= n2; ++i)
G.add_edge(i + n1, T, d[i + n1] - k);
ansflow = G.solve(T, S, T);
getans();
while (k--)
{
for (int i = 2 * m; i < G.ecnt; i += 2)
G.e[i].flow++;
ansflow = G.solve(T, S, T);
getans();
}
reverse(vecall(ans));
for (auto vec : ans)
{
cout << vec.size() << ' ';
for (auto i : vec)
cout << i << ' ';
putchar('\n');
}
}
int main()
{
TIME__START = clock();
int Test = 1;
// scanf(
while (Test--)
{
solve();
// if (Test)
// putchar('\n');
}
TIME__END = clock();
program_end();
return 0;
}
Comments NOTHING