题解:ABC395(A-E)

PS:由于作者后60分钟选择先做G题,所以他F和G都没做出来()

A - Strictly Increasing?

问题陈述

给你一个正整数 \(N\) 和一个长度为 \(N\) 的正整数序列 \(A = (A_1,A_2,\dots,A_N)\)

请判断 \(A\) 是否严格递增,即 \(A_i < A_{i+1}\) 是否对 \(1 \leq i < N\) 的每个整数 \(i\) 都成立。

思路

在线性搜索时判断当前元素与上一个元素的大小关系,如果为小于或等于则直接输出NO。

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 110;

int a[maxn];

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    int n;cin>>n;
    for(int i = 1;i <= n;i++){
        cin>>a[i];
        if(a[i] <= a[i-1]){
            cout<<"No";
            return 0;
        }
    }
    cout<<"Yes";
	return 0;
}

B - Make Target

问题陈述

概述**:创建一个 \(N \times N\) 模式,如下所示。

给你一个正整数 \(N\)

考虑一个 \(N \times N\) 网格。让 \((i,j)\) 表示从上往下第 \(i\) 行,从左往上第 \(j\) 列的单元格。最初,没有单元格被着色。

然后,依次对 \(i = 1,2,\dots,N\) 执行以下操作:

  • \(j = N + 1 - i\) .
  • 如果是 \(i \leq j\) ,则在左上角单元格为 \((i,i)\) 、右下角单元格为 \((j,j)\) 的矩形区域填充黑色(如果 \(i\) 为奇数),如果 \(i\) 为偶数,则填充白色。如果某些单元格已经着色,则覆盖它们的颜色。
  • 如果是 \(i &gt; j\) ,则不做任何操作。

经过所有这些操作后,可以证明没有未着色的单元格。确定每个单元格的最终颜色。

思路

小模拟,题面说什么跟着做什么就好,N非常小,不用考虑时间以及空间上的问题。

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 55;

int n;
char c[maxn][maxn];

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    cin>>n;
    for(int i = 1;i <= n;i++){
        int j = n + 1 -i;
        if(i <= j){
            if(i & 1){
                for(int a = i;a <= j;a++){
                    for(int b = i;b <= j;b++){
                        c[a][b] = '#';
                    }
                }
            }else{
                for(int a = i;a <= j;a++){
                    for(int b = i;b <= j;b++){
                        c[a][b] = '.';
                    }
                }
            }
        }
    }
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            cout<<c[i][j];
        }
        cout<<'\n';
    }
	return 0;
}

C - Shortest Duplicate Subarray

问题陈述

给你一个正整数 \(N\) 和一个长度为 \(N\) 的整数序列 \(A = (A_1,A_2,\dots,A_N)\)

请判断 \(A\) 中是否存在一个非空(连续)子数组,它有一个重复值,多次出现在 \(A\) 中。如果存在这样的子数组,求最短的子数组的长度。

思路

开桶判断有没有被记录过,如果记录过则把上一次记录的位置与当前位置之间的距离与ans进行判断,如果ans没有被更改过则输出-1。

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline
#define inf 0x3f3f3f3f

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 1e6+10;

struct node{
    bool vis;
    int pos;
}a[maxn];

int n,x,ans = inf;

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    cin>>n;
    for(int i = 1;i <= n;i++)
    {
        cin>>x;
        if(a[x].vis){
            ans = min(ans,i - a[x].pos + 1);
        }
        a[x].vis = 1;
        a[x].pos = i;
    }
    if(ans == inf){
        cout<<-1;
        return 0;
    }
    cout<<ans;
	return 0;
}

D - Pigeon Swap

问题陈述

\(N\) 只标有 \(1, 2, \ldots, N\) 的鸽子和 \(N\) 个标有 \(1, 2, \ldots, N\) 的鸽巢。

最初,鸽子 \(i\) \((1 \leq i \leq N)\) 在巢 \(i\) 中。

您将对这些鸽子进行 \(Q\) 次操作。

操作有三种:

  • 类型 \(1\) :给你整数 \(a\)\(b\)\((1 \leq a \leq N, 1 \leq b \leq N)\) .将鸽子 \(a\) 从当前巢中取出,移到巢 \(b\) 中。
  • 输入 \(2\) :给你整数 \(a\)\(b\)\((1 \leq a &lt; b \leq N)\) .将巢 \(a\) 中的所有鸽子移动到巢 \(b\) ,并将巢 \(b\) 中的所有鸽子移动到巢 \(a\) 。这两次移动同时进行。
  • 输入 \(3\) :给你一个整数 \(a\) \((1 \leq a \leq N)\) 。鸽子 \(a\) 报告它目前所在巢的标签。

按照给出的操作顺序打印每个 \(3\) 类型操作的结果。

思路

貌似以前见到过,记录分别记录鸽子的位置以及鸽巢编号,模拟出每次操作的效果即可。

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 1000010;

int n, m;
int p[maxn], q[maxn], pos[maxn];

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
	cin>>n>>m;
	for (int i = 1; i <= n; ++i)pos[i] = p[i] = q[i] = i;
	int t, a, b;
	while (m--)
    {
		cin>>t>>a;
		if (t == 1) {
            cin>>b;
			pos[a] = q[b];
        }else if (t == 2) {
            cin>>b;
			swap(q[a], q[b]);
			swap(p[q[a]], p[q[b]]);
		} else {
            cout<<p[pos[a]]<<'\n';
		}
	}
	return 0;
}

E - Flip Edge

问题陈述

问题陈述

给你一个有向图,图中有 \(N\) 个顶点和 \(M\) 条边。 \(i\) -th 边 \((1 \leq i \leq M)\) 是一条从顶点 \(u _ i\) 到顶点 \(v _ i\) 的有向边。

最初,您位于顶点 \(1\) 。您要重复以下操作直到到达顶点 \(N\)

  • 执行以下两个操作之一:
    • 从当前顶点沿一条有向边移动。这样做的代价是 \(1\) 。更精确地说,如果你在顶点 \(v\) ,选择一个顶点 \(u\) ,使得有一条从 \(v\)\(u\) 的有向边,然后移动到顶点 \(u\)
    • 逆转所有边的方向。这样做的代价是 \(X\) 。更确切地说,如果且仅如果在此操作之前有一条从 \(v\)\(u\) 的有向边,那么在此操作之后有一条从 \(u\)\(v\) 的有向边。

可以保证,对于给定的图,重复这些操作可以从顶点 \(1\) 到达顶点 \(N\)

求到达顶点 \(N\) 所需的最小总成本。

思路

跑dijstra的时候分别处理正向边和反向边,把得到的成本都放入优先队列内即可。

#include <bits/stdc++.h>
#define debug(a) cout << #a << "=" << a << '\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

typedef pair<ll, int> node;
const int maxn = 2e5 + 10;

int n, m, c;

ll a[maxn][2];
priority_queue<node, vector<node>, greater<node>> q;

struct E {
    int to, next;
} Edge[maxn], Rdge[maxn];

int tot, Head[maxn], Rtot, RHead[maxn];

inline void add1(int u, int v) {
    Edge[tot].to = v;
    Edge[tot].next = Head[u];
    Head[u] = tot++;
}

inline void add2(int u, int v) {
    Rdge[Rtot].to = v;
    Rdge[Rtot].next = RHead[u];
    RHead[u] = Rtot++;
}

int main() {
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
    ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
    cin >> n >> m >> c;
    memset(Head, -1, sizeof(Head));
    memset(RHead, -1, sizeof(RHead));
    memset(a, 0x3f, sizeof(a));
    for (int i = 0, x, y; i < m; ++i) {
        cin >> x >> y;
        add1(x, y);add2(y, x);
    }
    a[1][0] = 0ll;
    q.emplace(0ll, 2 * 1);
    while (!q.empty()) {
        auto [d, u] = q.top();
        q.pop();
        bool f = u & 1;
        u>>=1;
        if (a[u][f] != d)continue;
        
        if (u == n){cout<<d;return 0;}

        for (int i = Head[u];~i;i = Edge[i].next) {
            int v = Edge[i].to;
            ll w = d + 1 + (f ? c : 0);
            if (w < a[v][0]) {
                a[v][0] = w;
                q.emplace(w, 2 * v);
            }
        }

        for (int i = RHead[u];~i;i = Rdge[i].next) {
            int v = Rdge[i].to;
            ll w = d + 1 + (f ? 0 : c);
            if (w < a[v][1]) {
                a[v][1] = w;
                q.emplace(w, 2 * v + 1);
            }
        }
    }
    
    return 0;
}

posted @ 2025-03-01 21:41  Zheng_iii  阅读(64)  评论(0)    收藏  举报