Codeforces Round #816 (Div. 2)
\(\quad\) 今早头一次睡到了九点,大概昨天在健身房确实训练过度了,胸廓酸软,大腿一直颤抖。
\(\qquad\) 下午去了趟实验室,完成了我的第一个物联网程序虽然很水。慢慢试着用\(VS\quad CODE\)切题,效率一般,命令行与编译指令反而不知不觉间搞懂了……还是很垃圾,一整天只做出五道题,其中两道还是面向题解编程,日语没学,高数没学,前端没学,堆积的论文一篇没看,嗯,真是完美的一天。看着一整页的\(WA\)和自己初中生都不如的\(rating\),也只好苦笑一声继续推式子,一抬头发现那个女孩又给我发了消息,这次问的是道很简单的计数题,我正打算告诉她没设初始量时,想了想,决定晚点回。最近与她走得太近了点,有些行为事实上与情侣无异了,对我来说,过分了。现在的我还没有对任何人负起责任的资本,既然不想耽误别人的青春,还是保持距离的好。
\(\qquad\)明天就正式开课了,又会有幻梦的破碎,恍惚间已经预见到了。我还是想把一天一套\(Div.2\)的训练量坚持下去,现在的效率是不行的。得真正掌握些许许本领,才能堂堂正正地回到那座山。
\(\qquad\)说起来,九月的话,那个人的生日也近了
- A
简单找规律
$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
// ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int test;
cin >> test;
while(test--) {
int n, m;
cin >> n >> m;
if(n == 1 && m == 1) {
cout << "0\n";
}
else {
cout << (n + m - 2) * 2 - max(m - 2, n - 2) << "\n";
}
}
return 0;
}
/*
(m + n - 2) * 2 - max(m - 2, n - 2)
*/
- B
贪心,分析,普适化解构
$code$
# include "bits/stdc++.h"
using namespace std;
# define int long long
# undef int
int main() {
# define int long long
# ifdef QWQ
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
# endif
// ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int tt;
cin >> tt;
for(int t = 1; t <= tt; ++t) {
int n, k, b, s;
cin >> n >> k >> b >> s;
if(k * b + (k - 1) * n < s || s < b * k) {
cout << "-1\n";
}
else {
bool flag = true;
vector<int> ans;
// if(!ans.empty()) cout << "*****";
s -= b * k;
ans.push_back(b * k);
while(s > 0) {
int x = min(s, k - 1);
// cout << x << " ** " << endl;
s -= x;
ans.push_back(x);
if(ans.size() > n + 1) {
flag = false;
break;
}
}
if(flag == false) {
cout << "-1\n";
}
else {
if(ans.size() >= 2) {
ans[1] += ans[0];
ans.erase(ans.begin());
}
for(auto x : ans) {
cout << x << " ";
}
for(int i = ans.size() + 1; i <= n; ++i) {
cout << "0 ";
}
putchar('\n');
}
}
}
return 0;
}
/*
6
3 6 3 19
5 4 7 38
5 4 7 80
99978 1000000000 100000000 1000000000000000000
1 1 0 0
4 1000000000 1000000000 1000000000000000000
*/
/*
1
3 6 3 19
*/
/*
10
1 6 3 100
3 6 3 12
3 6 3 19
5 4 7 38
5 4 7 80
99978 1000000000 100000000 1000000000000000000
1 1 0 0
4 1000000000 1000000000 1000000000000000000
5 3 0 9
5 3 1 12
//n k b s
//
//5 3 0 9
// 0 2
// 9
*/
- C
全局思考每个点变化前后贡献变化,发现并基于边界展开讨论。过程中有些范围处理与线段树类似,弄清对象不足一提。
$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int n, m;
cin >> n >> m;
vector<int> a(n + 2, 0);
for(int i = 1; i <= n; ++i) {
cin >> a[i];
}
long long ans = 1ll * n * (n + 1) >> 1;
for(int i = 1; i <= n; ++i) {
if(a[i] != a[i + 1]) {
ans += 1ll * (n - i) * i;
}
}
// cout << ans << endl;
while(m--) {
int x;
cin >> x;
if(a[x] != a[x - 1]) ans -= 1ll * (n - x + 1) * (x - 1);
if(a[x] != a[x + 1]) ans -= 1ll * (n - x) * x;
cin >> a[x];
if(a[x] != a[x - 1]) ans += 1ll * (n - x + 1) * (x - 1);
if(a[x] != a[x + 1]) ans += 1ll * (n - x) * x;
cout << ans << "\n";
}
return 0;
}
- D
二进制问题,联想到基于数位贪心
$code$
# include "bits/stdc++.h"
using namespace std;
bool bit(int x, int i) {
return x & (1 << i - 1);
}
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
# endif
int n, m;
cin >> n >> m;
vector<int> ans(n + 1);
vector G(n + 1, vector<pair<int, int>>());
vector f(n + 1, bitset<32>());
for(int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
for(int j = 1; j <= 30; ++j) {
if(bit(w, j) == false) {
f[u][j] = f[v][j] = true; // here, we can't set f(node)(digit) := true when bit(w, j) == true, since some v may hasn't appered even once
}
}
if(u == v) {
ans[u] = w;
continue;
}
G[u].push_back({v, w});
G[v].push_back({u, w});
}
auto check = [&](int u, int i) -> bool {
for(auto [v, w] : G[u]) {
if(bit(w, i) == false) continue;
if(u < v) {
if(f[v][i] == true) return true;
}
else if(bit(ans[v], i) == false) return true;
}
return false;
};
for(int i = 1; i <= 30; ++i) {
for(int j = 1; j <= n; ++j) {
if(check(j, i) == true) {
ans[j] |= (1 << i - 1);
}
}
}
for(int i = 1; i <= n; ++i) cout << ans[i] << " ";
return 0;
}
- E
易知\(k=1\)时的情况,一定先走最短路最后才乌鸦坐飞机最优,算下\(\min {\{dis[u] + (v - u)^{2}} \}\)就可以。倘若每多一次飞翔,就相当于在上一次的最短(优?)路中再\(DP\)一次。跑\(K\)遍堆优\(dij\)即可。
注意到该题中,转移方程\(\{ dis_{new}= min \{dis_{now}+(u-v)^{2}\} \}\),可以化作 \(dis_{now}u + u^{2} = 2 * v * u + dis_{new}v - v ^{2}\),于是斜率优化,凸包维护。
需要注意的一点是,该题图像不保证连通,因此\(dij\)过程中需要把每个点都投入堆中。
$code$
# include "bits/stdc++.h"
using namespace std;
const int N = 100003;
int main() {
# define int long long
# ifdef QWQ
freopen("in.txt", "r", stdin);
# endif
int n, m, K;
cin >> n >> m >> K;
vector G(n + 1, vector<pair<int, int>>());
for(int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
G[u].push_back({v, w});
G[v].push_back({u, w});
}
vector<int> dis(n + 1);
auto dijkstra = [&]() -> void {
struct node {
int v, w;
bool operator < (const node &x) const {
return w > x.w;
}
};
priority_queue<node> q;
for(int i = 1; i <= n; ++i) q.push({i, dis[i]});
while(!q.empty()) {
auto [u, ww] = q.top();
q.pop();
if(ww != dis[u]) continue;
for(auto [v, w] : G[u]) {
if(dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({v, dis[v]});
}
}
}
};
for(int i = 1; i <= n; ++i) dis[i] = 1ll << 60;
dis[1] = 0;
dijkstra();
vector<int> stk(n + 2); // here, must >= n + 2, if we don't wanna get a whole page of unknown RE
vector<int> dis_new(n + 1);
auto slope = [&](int x, int y) -> double {
return 1.0 * (dis[y] + y * y - dis[x] - x * x) / (y - x);
};
while(K--) {
int top = 1;
stk[top] = 0;
for(int i = 1; i <= n; ++i) {
while(top > 1 && slope(stk[top - 1], stk[top]) > slope(stk[top], i)) --top;
stk[++top] = i;
}
int now = 1;
for(int i = 1; i <= n; ++i) {
while(now < top && slope(stk[now], stk[now + 1]) < 2 * i) ++now;
dis_new[i] = dis[stk[now]] + (i - stk[now]) * (i - stk[now]);
}
for(int i = 1; i <= n; ++i) dis[i] = dis_new[i];
// memcpy(dis, dis_new, (n + 1) * sizeof(int));
dijkstra();
}
for(int i = 1; i <= n; ++i) cout << dis[i] << " ";
return 0;
}
/*
2 1 1
2 1 893746473
*/