2020.7.13 解题报告
2020.7.13
\[\text{Happy Birthday!}
\]
\[\text{to Luckyblock}
\]
答题情况
总成绩 : 180 , 排名 : 1 / 8
T1 : 60 T2 : 20 T3 : 100
各题目分析
题目 1 :
预估成绩 : 100 实际成绩 : 60 考试用时 : 2:30 ~ 2:55
一眼秒,直接写标算。
拍了1w 组数据。
最后犹豫开不开 long long,偷懒没开。
哭了。
题目 2 :
预估成绩 : 20 实际成绩 : 20 考试用时 : 4:30 ~ 5:20
神题,写了20。
题目 3 :
预估成绩 : 100 实际成绩 : 100 考试用时 : 3:00 ~ 4:00
一眼秒,直接写标算。
拍了1w 组数据。
题目解析
T1
预处理 f 和 g。排序离散后相当于 逆序对问题。
用线段树或者树状数组统计答案即可。
T2
对于 20%的数据:暴力 Dfs 每次都在哪里升级。
对于 30-40%的数据:由于 R 为 0,直接二分答案,枚举判断。
对于 50-60%的数据:二分答案,一个显然的性质是如果[1,x-1]的区间都已经满足条件,那么这
一次升级放在 x+R-1 点一定答案最优。问题变成区间加,单点查询,用线段树或树状数组能方便
的查询。
对于 70%-100%的数据:发现这个问题和“滑窗问题”类似。考虑用一个单调队列来维护当前区间
被升级了多少次。
T3
离线。对询问排序,从小到大向一个空图加边。加边后用一个并查集维护连通性。
又因为加边后答案是单调递增的,能很方便的维护最大值。
代码实现
T1 :
考场代码
//
/*
By:Luckyblock
实际上是个逆序对 问题
树状数组水一水
*/
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define lowbit(x) (x&-x)
#define ll long long
const int kMaxn = 3e5 + 10;
//=============================================================
struct Data {
ll val, id;
int pos;
} data[kMaxn];
struct Tom {
ll a, f, g, id;
} a[kMaxn];
int n, k, maxx, ans, t[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
ll qmul(ll x, ll y) {
ll ret = 1;
while (y) {
if (y & 1) ret = ret * x % k;
x = x * x % k, y >>= 1;
}
return ret;
}
bool Compare(Data fir, Data sec) {
return fir.val < sec.val;
}
void Modify(int pos, int val) {
for (int i = pos; i <= maxx; i += lowbit(i)) t[i] += val;
}
int Query(int pos) {
int ret = 0;
for (int i = pos; i; i -= lowbit(i))
ret += t[i];
return ret;
}
//=============================================================
int main() {
freopen("Calc.in", "r", stdin);
freopen("Calc.out", "w", stdout);
n = read(), k = read();
for (int i = 1; i <= n; ++ i) {
a[i].a = (ll) read();
a[i].f = qmul(i, a[i].a);
a[i].g = qmul(a[i].a, i);
data[i] = (Data) {a[i].a, i, 1};
data[n + i] = (Data) {a[i].f, i, 2};
data[2 * n + i] = (Data) {a[i].g, i, 3};
}
std :: sort(data + 1, data + 3 * n + 1, Compare);
data[0].val = - 114514;
for (int i = 1; i <= 3 * n; ++ i) {
if (data[i].val > data[i - 1].val) maxx ++;
if (data[i].pos == 1) a[data[i].id].a = maxx;
if (data[i].pos == 2) a[data[i].id].f = maxx;
if (data[i].pos == 3) a[data[i].id].g = maxx;
}
for (int i = 1; i <= n; ++ i) {
ans += Query(maxx) - Query(a[i].g);
Modify(a[i].f, 1);
}
printf("%d\n", ans);
return 0;
}
//暴力
/*
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define lowbit(x) (x&-x)
#define ll long long
const int kMaxn = 1e5 + 10;
//=============================================================
struct Tom {
ll a, f, g, id;
} a[kMaxn];
int n, k, ans;
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
ll qmul(ll x, ll y) {
ll ret = 1;
while (y) {
if (y & 1) ret = ret * x % k;
x = x * x % k, y >>= 1;
}
return ret;
}
//=============================================================
int main() {
freopen("Calc.in", "r", stdin);
freopen("2.out", "w", stdout);
n = read(), k = read();
for (int i = 1; i <= n; ++ i) {
a[i].a = (ll) read();
a[i].f = qmul(i, a[i].a);
a[i].g = qmul(a[i].a, i);
}
for (int l = 1; l <= n; ++ l) {
for (int r = l + 1; r <= n; ++ r) {
if (a[l].f > a[r].g) ans ++;
}
}
printf("%d\n", ans);
return 0;
}
*/
//数据生成器
/*
#include <bits/stdc++.h>
#include <ctype.h>
#include <algorithm>
#define ll long long
const int kMaxn = 1e4;
const int kMaxk = 1e9;
//=============================================================
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
//=============================================================
int main() {
freopen("Calc.in", "w", stdout);
srand(time(0));
int n = rand() % kMaxn + 1, k = kMaxk;
printf("%d %d\n", n, k);
for (int i = 1; i <= n; ++ i) {
printf("%d ", rand() % kMaxk + 1);
}
return 0;
}
*/
//checker
/*
#include <bits/stdc++.h>
#include <ctype.h>
#include <algorithm>
#define ll long long
//=============================================================
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
//=============================================================
int main() {
for (int i = 1; ; ++ i) {
system("datamaker.exe");
system("Calc.exe");
system("Calcbaoli.exe");
printf("%d ", i);
if (system("fc Calc.out 2.out")) break;
}
return 0;
}
*/
T2:
考场代码
//
/*
By:Luckyblock
神题
*/
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define ll long long
const int kMaxn = 5e5 + 10;
//=============================================================
ll n, r, k, a[kMaxn];
ll maxx, cnt[kMaxn], map[kMaxn], delta[kMaxn];
//=============================================================
inline ll read() {
ll f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
//=============================================================
int main() {
freopen("Game.in", "r", stdin);
freopen("Game.out", "w", stdout);
n = read(), r = read(), k = read();
for (int i = 1; i <= n; ++ i) a[i] = read();
std :: sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++ i) {
if (a[i] > a[i - 1]) {
delta[maxx] = a[i] - a[i - 1];
map[++ maxx] = a[i];
}
cnt[maxx] ++;
}
for (int i = 1; i < maxx; ++ i) {
ll need = cnt[i] * delta[i];
if (need > k) {
printf("%lld", map[i] + (k / cnt[i]));
return 0;
}
if (need == k) {
printf("%lld", map[i]);
return 0;
}
k -= need;
cnt[i + 1] += cnt[i];
}
printf("%lld", map[maxx] + (k / n));
return 0;
}
/*
5 0 100
1 200 4 3 50
*/
T3:
考场代码
//
/*
By:Luckyblock
并查集水一水
发现暴力写挂啦
最后拍上了
*/
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define ll long long
const int kMaxn = 1e5 + 10;
//=============================================================
struct Edge {
int u, v, w;
} e[kMaxn << 1];
struct Query {
int q, id;
} q[kMaxn];
int n, m, k, edge_num, id[kMaxn];
int bel[kMaxn];
int nowans, sum[kMaxn], ans[kMaxn];
//============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
void AddEdge(int u, int v, int w) {
e[++ edge_num].u = u, e[edge_num].v = v, e[edge_num].w = w;
}
bool CompareEdge(Edge fir, Edge sec) {
return fir.w < sec.w;
}
bool CompareQuery(Query fir, Query sec) {
return fir.q < sec.q;
}
int Find(int x) {
return x == bel[x] ? x : bel[x] = Find(bel[x]);
}
void Unico(int x, int y, int w) {
int r1 = Find(x), r2 = Find(y);
bel[r2] = r1;
sum[r1] += sum[r2] + w;
GetMax(nowans, sum[r1]);
}
//=============================================================
int main() {
freopen("Graph.in", "r", stdin);
freopen("Graph.out", "w", stdout);
n = read(), m = read(), k = read();
for (int i = 1; i <= m; ++ i) {
int u = read(), v = read(), w = read();
AddEdge(u, v, w);
}
for (int i = 1; i <= k; ++ i) {
q[i].q = read(), q[i].id = i;
}
std :: sort(q + 1, q + k + 1, CompareQuery);
std :: sort(e + 1, e + edge_num + 1, CompareEdge);
for (int i = 1; i <= n; ++ i) bel[i] = i;
for (int i = 1, j = 1; i <= k; ++ i) {
for (; j <= edge_num && e[j].w <= q[i].q; ++ j) {
int u = e[j].u, v = e[j].v, w = e[j].w;
if (Find(u) == Find(v)) {
sum[Find(u)] += w;
GetMax(nowans, sum[Find(u)]);
} else {
Unico(u, v, w);
}
}
ans[q[i].id] = nowans;
}
for (int i = 1; i <= k; ++ i) printf("%d\n", ans[i]);
return 0;
}
//暴力
/*
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm>
#define ll long long
const int kMaxn = 1e5 + 10;
//=============================================================
struct Edge {
int u, v, w, ne;
} e[kMaxn << 1], e1[kMaxn << 1];
int n, m, k, edge_num, edge_num1, ans, sum[kMaxn], head1[kMaxn];
bool vis[kMaxn], use[kMaxn << 1];
//============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
void AddEdge(int u, int v, int w) {
e[++ edge_num].u = u, e[edge_num].v = v, e[edge_num].w = w;
}
void AddEdge1(int u, int v, int w) {
e1[++ edge_num1].u = u, e1[edge_num1].v = v, e1[edge_num1].w = w;
e1[edge_num1].ne = head1[u], head1[u] = edge_num1;
}
bool Compare(Edge fir, Edge sec) {
return fir.w < sec.w;
}
void Dfs(int u, int root) {
vis[u] = true;
for (int i = head1[u]; i >= 0; i = e1[i].ne) {
if (use[i]) continue ;
sum[root] += e1[i].w;
use[i] = true;
use[i ^ 1] = true;
Dfs(e1[i].v, root);
}
}
//=============================================================
int main() {
freopen("Graph.in", "r", stdin);
freopen("Graphbaoli.out", "w", stdout);
n = read(), m = read(), k = read();
for (int i = 1; i <= m; ++ i) {
int u = read(), v = read(), w = read();
AddEdge(u, v, w);
}
std :: sort(e + 1, e + edge_num + 1, Compare);
for (int i = 1; i <= k; ++ i) {
memset(head1, 128, sizeof(head1));
memset(vis, 0, sizeof(vis));
memset(use, 0, sizeof(use));
memset(sum, 0, sizeof(sum));
ans = 0; edge_num1 = - 1;
int q = read();
for (int j = 1; j <= edge_num && e[j].w <= q; ++ j) {
AddEdge1(e[j].u, e[j].v, e[j].w);
AddEdge1(e[j].v, e[j].u, e[j].w);
}
for (int i = 1; i <= n; ++ i) {
if (vis[i]) continue ;
Dfs(i, i);
GetMax(ans, sum[i]);
}
printf("%d\n", ans);
}
return 0;
}
*/
//数据生成器
/*
#include <bits/stdc++.h>
#include <ctype.h>
#include <algorithm>
#define ll long long
const int kMaxn = 10000;
const int kMaxw = 1000;
//=============================================================
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
//=============================================================
int main() {
freopen("Graph.in", "w", stdout);
srand(time(0));
int n = rand() % kMaxn + 1,
m = rand() % kMaxn + 1,
q = rand() % kMaxn + 1;
printf("%d %d %d\n", n, m, q);
for (int i = 1; i <= m; ++ i) {
int u = rand() % n + 1, w = rand() % kMaxw + 1, v;
do v = rand() % n + 1;
while (u == v);
printf("%d %d %d\n", u, v, w);
}
for (int i = 1; i <= q; ++ i) {
printf("%d\n", rand() % kMaxw + 1);
}
return 0;
}
*/
//checker
/*
#include <bits/stdc++.h>
#include <ctype.h>
#include <algorithm>
#define ll long long
//=============================================================
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
//=============================================================
int main() {
for (int i = 1; ; ++ i) {
system("datamakerGraph.exe");
system("Graph.exe");
system("Graphbaoli.exe");
printf("%d ", i);
if (system("fc Graph.out Graphbaoli.out")) break;
}
return 0;
}
*/
作者@Luckyblock,转载请声明出处。