CWOI 2025.03.21 考试

T1 CF1427D Unshuffling a Deck

神秘构造题,赛场上的构造太劣了挂了 24pts。

首先,\(w\) 的范围明示需要 \(n\) 次操作以内排完,所以我们考虑每次让升序序列变长 \(1\),可以发现,如果我们的序列是 \([x + 1,\ldots,x,\ldots]\),那我们就可以把 \(x + 1\) 翻到 \(x\) 后面去,同时如果 \(x + 1\) 后面已经有序,那我们就可以一起翻过去,这样就可以在 $ O(n)$ 次操作内排完序。

T2 CF1473E Minimum Path

之前做过的原题,首先,原题中的限制相当于最短路加上最小边权,减去最大边权,根据贪心思想,我们又可以将限制弱化为加上一条边的边权,减去一条边的边权,因为加上的一定是最小的,减去的一定是最大的。

我们可以考虑分层图,第一层是没考虑 \(\min\)\(\max\) 的,第二层是只考虑了 \(\max\) 的,第三层是只考虑了 \(\min\) 的,第四层是既考虑了 \(\min\) 又考虑了 \(\max\) 的,答案就是第四层的 \(dis\),跑一遍 Dijkstra 就好了。

T3 Luogu P5532 [CCO 2019] Sirtet

第一眼还以为是大模拟,就直接没写,赛后听 zcy 说 SPFA 被卡了,才知道这是个差分约束。

我们可以将问题转化为每一个点向下掉的最大距离。

先分类讨论一下,如果下面是 .,则可以向下掉,连边权为 \(1\) 的边,否则,就不能,连边权为 \(0\) 的边。联通块内相邻的点互相连边权为 \(0\) 的边,然后可以直接跑 01bfs(但是 01bfs 为什么跑不过带 \(\log\) 的 Dijkstra),统计答案即可。

T4 还没改。

这个得贴个代码,有点抽象。

#include <bits/extc++.h>
#define int long long
#define pii pair<int,int>
using namespace std;

constexpr int MAXN = 1e6 + 5,MV[4][2]{{1,0},{-1,0},{0,1},{0,-1}};
int n,m,dis[MAXN];
inline int getID(int x,int y)
{return (x - 1) * m + y;}
vector<vector<char> > ch,ans;
vector<pii> g[MAXN];
bool Vis[MAXN],vis[MAXN];
inline void dfs(int x,int y,int pre)
{
    Vis[getID(x,y)] = 1;
    if(pre)
        g[getID(x,y)].emplace_back(pre,0),g[pre].emplace_back(getID(x,y),0);
    for(int i = 0;i < 4;i++)
    {
        int dx = x + MV[i][0],dy = y + MV[i][1];
        if(dx < 1 || dx > n || dy < 1 || dy > m || Vis[getID(dx,dy)] || ch[dx][dy] == '.')
            continue;
        dfs(dx,dy,getID(x,y));
    }
}
inline void bfs()
{
    deque<pii> q;
    memset(dis,0x3f,sizeof(dis));
    for(int i = 1;i <= m;i++)
        q.emplace_back(getID(n,i),0);
    while(!q.empty())
    {
        int u = q.front().first,d = q.front().second;
        q.pop_front();
        if(vis[u])
            continue;
        vis[u] = 1,dis[u] = d;
        for(auto& [v,w] : g[u])
        {
            if(!w)
                q.emplace_front(v,d);
            else
                q.emplace_back(v,d + 1);
        }
    }
}
signed main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin >> n >> m;
    ch.resize(n + 1),ans.resize(n + 1);
    for(int i = 1;i <= n;i++)
    {
        ch[i].resize(m + 1),ans[i].resize(m + 1,'.');
        for(int j = 1;j <= m;j++)
            cin >> ch[i][j];
    }
    for(int i =  1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)
        {
            if(!Vis[getID(i,j)] && ch[i][j] == '#')
                dfs(i,j,0);
        }
    }
    for(int i = 1;i < n;i++)
    {
        for(int j = 1;j <= m;j++)
        {
            if(ch[i + 1][j] == '.')
                g[getID(i + 1,j)].emplace_back(getID(i,j),1);
            else if(ch[i][j] == '.')
                g[getID(i + 1,j)].emplace_back(getID(i,j),0);
        }
    }
    bfs();
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)
        {
            if(ch[i][j] == '#')
                ans[i + dis[getID(i,j)]][j] = '#';
        }
    }
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)
            cout << ans[i][j];
        cout << "\n";
    }
}
posted @ 2025-03-24 12:04  xguagua_233  阅读(33)  评论(0)    收藏  举报