10.9 补题记录

d-p-n-i- / 2024-10-11 / 原文

ok呀今天又是痛苦vp的一天 坐牢啊坐牢啊https://contest.ucup.ac/contest/1412/problem/7755
其实L题好早就知道这么做了就是写不清楚写了好久好久 太浪费时间了!!!我的苍天啊 码代码能力真的烂
好吧好吧 补题了 冒泡排序好像有点忘记了 等我明天听听课回忆回忆 先放代码(我来解析了)
就是说我们的操作1把第一个数移动到后面相当于把指针向后移动一位
操作2就是把第二个数字移动到最后也就是说交换了指针所指向的数和他下一个数的相对位置(swap(a[t],a[t+1]))
然后我们每一轮都把一个数放到他正确的位置上就okk
okok我回来了 我补完了 代码非常简单:
void solve()
{
int n;
string s="";
map<int,int>mp;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) {cin>>b[i];mp[b[i]]=i;}
int cnt=n-1;
int t=1;
while(cnt)
{
int ans=cnt;
while(ans--)
{
if(mp[a[t]]<mp[a[t+1]])//正确 指针下一位
{
s+='1';
}
else //不正确换一下位置
{
s+='2';
swap(a[t],a[t+1]);
}
t++;
}
int m=n-cnt;
while(m--) s+='1';//把指针移动回第一位
t=1;
cnt--;
}
int k=0;
for(int i=1;i<=n;i++)
{
if(a[i]b[1])
{
k=i;
break;
}
}
if(k
1) cout<<s<<endl;
else
{
k=n-k+1;
while(k--) s+='1';
cout<<s<<endl;
}

}

然后就是我们的博弈啦 是赛后看的感觉挺有感觉的不知道赛时能不能写出来
sg函数啊 我感觉我对这个函数一知半解的就是感觉能理解为什么 但是让我自己构造我不太行 再理解理解
ok我好像懂了 先学https://zhuanlan.zhihu.com/p/257013159 (sg函数)

include<bits/stdc++.h>

using namespace std;

define int long long

define fi first

define se second

using PII = pair<int, int>;
int x[1001000],y[1001000],e[1001000],h[1001000],ne[1001000],idx;
struct DSU {
std::vector f;
std::vector size;

DSU(int n) : f(n), size(n) {
    std::iota(f.begin(), f.end(), 0);
    std::fill(size.begin(), size.end(), 1);
}

int find(int x) {
    while (x != f[x])
        x = f[x] = f[f[x]];
    return x;
}

void Union(int x, int y) {
    if (find(x) == find(y))
        return;

    size[find(x)] += size[find(y)];
    f[find(y)] = find(x);
}

int blockSize(int x) {
    return size[find(x)];
}

};

int sg(int x) {
if (x == 0)
return 0;
return 2 - x % 2;
}

signed main()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);

int n, m;
std::cin >> n >> m;

DSU dsu(n + 1); // 开个并查集

std::vector e(n + 1, std::vector<int>());
for (int u, v, i = 0; i < m; i++) {
    std::cin >> u >> v;
    dsu.Union(u, v);
    e[u].push_back(v);
    e[v].push_back(u);
}

int SG = 0;
for (int i = 1; i <= n; i++) {
    if (dsu.find(i) == i)
        SG ^= sg(dsu.blockSize(i));
}

int ans = 0;
std::vector<int> size(n + 1, 0);
std::function<void(int, int)> dfs = [&](int x, int fa) {//size就是这个点和他儿子的全部
    size[x] = 1;
    int tmpSG = 0;
    for (int y : e[x]) {
        if (y == fa)
            continue;
        dfs(y, x);
        size[x] += size[y];
        tmpSG ^= sg(size[y]);//把他全部的儿子的值都^上
    }

    tmpSG ^= sg(dsu.blockSize(x) - size[x]);//这个块的总数 减去这个点的子子孙孙(太聪明了wk 因为另外一半是一定是一颗完整的树 所以可以放sg里 然后此时的tmpSG他又^上了他的所以儿子 所以完美结束)
    // 删点
    if ((SG ^ tmpSG) == 0)
        ans++;

    // 删边
    if (fa != 0 and (SG ^ sg(size[x]) ^ sg(dsu.blockSize(x) - size[x])) == 0) {
        ans++;
    }
};


for (int i = 1; i <= n; i++) {
    if (dsu.find(i) == i) {//找每一个块
        SG ^= sg(dsu.blockSize(i));
        dfs(i, 0);
        SG ^= sg(dsu.blockSize(i));
    }
}

std::cout << ans;

}

完结撒花!!