LGP8346 「Wdoi-6」最澄澈的空与海
原题链接:「Wdoi-6」最澄澈的空与海
分析
这个结论是好猜的吧......
就相当于是,我第一要求原图联通(不存在 deg 为 0 0 0 的点),第二,我要求存在两个 deg 为 2 2 2 的点,且这两个点之间有连边,也必须属于两部?
有没有漏什么性质?
这输入格式也太反人类了吧?
写了一些奇怪的状物,其实底层是判断一些可以多次配对的东西,不出意外地 WA 了。看一下题解。
我们看到了类似于 deg 的东西,那不妨借用 toposort 的思路,直接写就行了。
都有 d e g deg deg 和环了,你还想不到拓扑排序?
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int T;
int n, m;
int deg[N << 1];
vector<int> e[N << 1];
bool vis[N << 1];
void init(){
for (int i = 1; i <= 2 * n; i++) {
e[i].clear();
deg[i] = 0;
vis[i] = false;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> T;
for (int cs = 1; cs <= T; cs++){
init();
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++){
cin >> u >> v;
e[u].push_back(v + n);
e[v + n].push_back(u);
deg[u]++;
deg[v + n]++;
}
queue<int> q;
for (int i = 1; i <= n * 2; i++){
q.push(i);
}
int cnt = 0;
while (!q.empty()){
int u = q.front();
q.pop();
if (vis[u] || deg[u] != 1)
continue;
int tmp = -1;
for (auto v : e[u]){
if (!vis[v]){
tmp = v;
break;
}
}
if (tmp == -1)
continue;
vis[u] = vis[tmp] = true;
cnt += 2;
for (auto v : e[tmp]){
if (!vis[v]){
deg[v]--;
if (deg[v] == 1){
q.push(v);
}
}
}
}
if (cnt == n * 2)
cout << "Renko" << '\n';
else
cout << "Merry" << '\n';
}
}
LGP12848 蓝桥杯 2025 国 A 游戏
原题链接:蓝桥杯 2025 国 A 游戏
分析
好像要求出来,就是我们似乎往 n n n 连边是优的?就是找 1 1 1 的数的个数?这个怎么证明正确啊Σ(っ °Д °;)っ
别急,我猜他和最长上升子序列有关系。别急,好像还真让我猜到了什么。不过不全......
被证实了一些东西......不过,我们好像直接写一个树状数组......然后......还有什么吗?我也不知道😭
bur,咋才能把这个东西想得更清楚呢?
我要看题解了😭
答案一定不超过 2 2 2!!!
哦,我们连一下 ( 1 , n ) (1,n) (1,n) 和 ( n − 2 , n ) (n-2,n) (n−2,n)!
哦,就是说,因为始终有 n n n 的位置可以保证为空,则我们直接做就行了。
这是个题?跳了我😭
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 300005;
int n, a[N];
bool check0(){
for (int i = 1; i < n; i++){
if (a[i] != i)
return false;
}
return true;
}
bool check1(){
int L = 1, R = n - 1;
while (L < n && a[L] == L)
L++;
while (R >= 1 && a[R] == R)
R--;
if (L > R)
return true;
int pos = 0;
for (int i = L; i <= R; i++){
if (a[i] == R){
pos = i;
}
}
for (int i = pos; i >= L; i--){
if (a[i] != R - (pos - i))
return false;
}
for (int i = pos + 1; i <= R; i++){
if (a[i] != L + (i - pos - 1))
return false;
}
return true;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i < n; i++){
cin >> a[i];
}
if (check0()){
cout << 0;
return 0;
}
if (check1()){
cout << 1;
return 0;
}
else{
cout << 2;
return 0;
}
}
AT_arc227_f ARC227F Erase and Raise
原题链接:F. Erase and Raise
LGP1381 单词背诵
原题链接:单词背诵
分析
难道说,我邪修一下,对于第一个答案,拿一个 map 写一下,第二个,我拿两个模数写一个前缀和状物......这真的对吗?
但是,精细实现可以通过 O ( m n ) O(mn) O(mn),对的......
但是,那是没有意义的啊......一般来说,我可能会写一个字典树吗?那不是......不对,字典树并不对。
所以,到底怎么做😭
那个 map 竟然随便做,我力竭了......
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m;
string s[N], t[N];
map<string, int> sum;
map<string, bool> buc;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++){
cin >> s[i];
buc[s[i]] = true;
}
cin >> m;
int pos = 1;
int cnt = 0;
int ans = 0x3f3f3f3f;
for (int i = 1; i <= m; i++){
cin >> t[i];
if (buc[t[i]]){
sum[t[i]]++;
}
if (sum[t[i]] == 1){
cnt++;
ans = i - pos + 1;
}
while (pos <= i){
if (!buc[t[pos]]){
pos++;
continue;
}
if (sum[t[pos]] >= 2){
sum[t[pos]]--;
pos++;
continue;
}
break;
}
ans = min(ans, i - pos + 1);
}
cout << cnt << '\n';
cout << ans;
}
LGP8347 「Wdoi-6」另一侧的月
原题链接:「Wdoi-6」另一侧的月
分析
别急,操作次数是否一定呢?
我又双叒叕读错题了😭
就是说,我每次操作,肯定要找到一个对于当前是有利的对吧。怎么说呢?就是说......
不是,我都看了两集战锤了,为啥还不会???
对于一条链......这个怎么做?
菊花和完全二叉树是好做的对吧......或者说我蒙对了......
一旦一个节点的度数为偶数,则先手必胜;反之,后手必胜。证明显然,和我们蒙出来的差不多。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int T;
int n;
int deg[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> T;
for (int cs = 1; cs <= T; cs++){
memset(deg, 0, sizeof(deg));
cin >> n;
for (int i = 1, u, v; i < n; i++){
cin >> u >> v;
deg[u]++;
deg[v]++;
}
bool flag = false;
for (int i = 1; i <= n; i++){
if (deg[i] % 2 == 0){
flag = true;
break;
}
}
if (flag)
cout << "Hifuu" << '\n';
else{
cout << "Luna" << '\n';
}
}
}
所以说,博弈论系列题目,其实,你想到一个贪心之后,我们只需要再次进行推广即可得到正确的博弈判断。
LGP5043 【模板】树同构 / BJOI2015 树的同构
分析
努力理解一下......
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 55;
const int rnd = mt19937_64(time(0))();
int gethash(int x){
x ^= rnd;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
x ^= rnd;
return x;
}
int m;
int n;
vector<int> e[N];
int w[N], rt[N];
map<int, int> tr;
void dfs(int u){
w[u] = 1;
for (auto v : e[u]){
dfs(v);
w[u] += gethash(w[v]);
}
}
void getrt(int u){
for (auto v : e[u]){
rt[v] = w[v] + gethash(rt[u] - gethash(w[v]));
getrt(v);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> m;
for (int cs = 1; cs <= m; cs++){
for (int i = 1; i <= n; i++){
e[i].clear();
}
int root = 0;
cin >> n;
for (int i = 1, fa; i <= n; i++){
cin >> fa;
if (fa == 0){
root = i;
continue;
}
e[fa].push_back(i);
}
dfs(root);
rt[root] = w[root];
getrt(root);
int tmp = 1;
for (int i = 1; i <= n; i++){
tmp += gethash(rt[i]);
}
if (tr.find(tmp) == tr.end()){
tr[tmp] = cs;
}
cout << tr[tmp] << '\n';
}
}
LGP1510 精卫填海
原题链接:精卫填海
分析
第 999 999 999 道题......
直接
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int v, n, c;
int k[N], m[N];
int dp[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> v >> n >> c;
for (int i = 1; i <= n; i++){
cin >> k[i] >> m[i];
}
for (int i = 1; i <= n; i++){
for (int j = c; j >= m[i]; j--){
dp[j] = max(dp[j], dp[j - m[i]] + k[i]);
}
}
for (int j = 0; j <= c; j++){
if (dp[j] >= v){
cout << c - j;
return 0;
}
}
cout << "Impossible";
return 0;
}
LGP17413 「IXOI R3」时间复杂度分析
原题链接:「IXOI R3」时间复杂度分析
分析
第 1000 1000 1000 道题,始于红题,终于红题......前路漫漫,加油!
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500000000;
int n;
signed main(){
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
cin >> n;
if (n > N){
cout << "O(1)";
return 0;
}
else if (n * n <= N){
cout << "O(n^2)";
return 0;
}
else if (n <= N){
cout << "O(n)";
return 0;
}
else{
cout << "O(1)";
return 0;
}
}