AtCoder Beginner Contest 395


A - Strictly Increasing?

题意:判断A是不是严格递增。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    for (int i = 1; i < n; ++ i) {
    	if (a[i] <= a[i - 1]) {
    		std::cout << "No\n";
    		return;
    	}
    }

    std::cout << "Yes\n";
}

B - Make Target

按题意直接模拟模拟。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<std::string> s(n, std::string(n, '.'));
    for (int i = 0; i < n; ++ i) {
    	int j = n - i - 1;
    	if (i <= j) {
    		char c = i % 2 ? '.' : '#';
    		for (int x = i; x <= j; ++ x) {
    			for (int y = i; y <= j; ++ y) {
    				s[x][y] = c;
    			}
    		}
    	}
    }

    for (int i = 0; i < n; ++ i) {
    	std::cout << s[i] << "\n";
    }
}

C - Shortest Duplicate Subarray

题意:求最短的有至少两个一样元素的子数组长度。

从前往后记录每个数出现的上一个位置。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    const int N = 1e6 + 5;
    std::vector<int> last(N, -1);
    int ans = -1;
    for (int i = 0; i < n; ++ i) {
    	if (last[a[i]] != -1) {
    		if (ans == -1 || i - last[a[i]] + 1 < ans) {
    			ans = i - last[a[i]] + 1;
    		}
    	}

    	last[a[i]] = i;
    }

    std::cout << ans << "\n";
}

D - Pigeon Swap

题意:有n个巢穴,第i个鸽子在第i个巢穴。有三种操作:

  1. 把第i个鸽子放到第j个巢穴。
  2. 把第i个巢穴的鸽子和第j个巢穴的鸽子交换。
  3. 询问第i个鸽子在第几个巢穴。

转换一下题意,第i个巢穴上贴上了编号为i的标签,第二个操作视为交换两个巢穴的标签,第三个操作视为询问鸽子所在巢穴的标签。
那么记idai为第i个鸽子所在的巢穴的标签编号,idbi表示第i个巢穴上面的标签编号, idci表示第i个标签所在的巢穴编号。
那么对于每个询问,我们直接输出idcidai。对于操作一,就是idai=idbj,对于操作二,我们需要交换两个巢穴的编号,那么需要更新idb以及idc,先swap(idcidbi,idcidbj),交换两个标签的巢穴编号,再swap(idbi,idbj),交换两个巢穴的标签。

点击查看代码
void solve() {
    int n, q;
    std::cin >> n >> q;
    std::vector<int> ida(n), idb(n), idc(n);
    std::iota(ida.begin(), ida.end(), 0);
    std::iota(idb.begin(), idb.end(), 0);
    std::iota(idc.begin(), idc.end(), 0);
    while (q -- ) {
    	int op;
    	std::cin >> op;
    	if (op == 1) {
    		int a, b;
    		std::cin >> a >> b;
    		-- a, -- b;
    		ida[a] = idb[b];
    	} else if (op == 2) {
    		int a, b;
    		std::cin >> a >> b;
    		-- a, -- b;
    		std::swap(idc[idb[a]], idc[idb[b]]);
    		std::swap(idb[a], idb[b]);
    	} else {
    		int a;
    		std::cin >> a;
    		-- a;
    		std::cout << idc[ida[a]] + 1 << "\n";
    	}
    }
}

E - Flip Edge

题意:给你一个有向图,你可以花1的代价按边走,或者花费x的代价使得所有边翻转。求1n的最小花费。

存一个原图和反图,然后记dist[i][j]为在i点且图是不是反的状态的最短距离。
然后就可以dijkstra

点击查看代码
void solve() {
    int n, m, x;
    std::cin >> n >> m >> x;
    std::vector adj(2, std::vector(n, std::vector<int>{}));
    for (int i = 0; i < m; ++ i) {
    	int u, v;
    	std::cin >> u >> v;
    	-- u, -- v;
    	adj[0][u].push_back(v);
    	adj[1][v].push_back(u);
    }

    const i64 inf = 1e18;
    std::vector dist(n, std::array<i64, 2>{inf, inf});
    using A = std::array<i64, 3>;
    std::priority_queue<A, std::vector<A>, std::greater<A>> heap;
    dist[0][0] = 0;
    heap.push({dist[0][0], 0, 0});
    while (heap.size()) {
    	auto [d, u, t] = heap.top(); heap.pop();
    	if (d != dist[u][t]) {
    		continue;
    	}

    	for (auto & v : adj[t][u]) {
    		if (dist[v][t] > dist[u][t] + 1) {
    			dist[v][t] = dist[u][t] + 1;
    			heap.push({dist[v][t], v, t});
    		}
    	}

    	for (auto & v : adj[t ^ 1][u]) {
    		if (dist[v][t ^ 1] > dist[u][t] + x + 1) {
    			dist[v][t ^ 1] = dist[u][t] + x + 1;
    			heap.push({dist[v][t ^ 1], v, t ^ 1});
    		}
    	}
    }

    std::cout << std::min(dist[n - 1][0], dist[n - 1][1]) << "\n";
}

F - Smooth Occlusion

题意:给你两个数组a,b,你可以让a,b里的任意数减少任意值,但要大于0。使得满足i,j[1,n],ai+bi=aj+bji[1,n1]|aiai+1|x and |bibi+1|x。求减少的最小值。

先考虑满足任意相邻的两个数相差不超过x。那么我们从前往后扫一遍,使得ai=min(ai,ai1+x),然后从后往前扫一遍,使得ai=min(ai,ai+1+x)。同时对b也这么做。那么这样后,每个数就是满足条件的最大值了。于是我们取最小的ai+bi,让其它位置的总和也减到这个长度就行了。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<i64> a(n), b(n);
    i64 sum = 0;
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i] >> b[i];
    	sum += a[i] + b[i];
    }

    for (int i = 1; i < n; ++ i) {
    	a[i] = std::min(a[i], a[i - 1] + m);
    	b[i] = std::min(b[i], b[i - 1] + m);
    }

    for (int i = n - 2; i >= 0; -- i) {
    	a[i] = std::min(a[i], a[i + 1] + m);
    	b[i] = std::min(b[i], b[i + 1] + m);
    }

    i64 min = 2e9;
    for (int i = 0; i < n; ++ i) {
    	min = std::min(min, a[i] + b[i]);
    }

    std::cout << sum - n * min << "\n";
}
posted @   maburb  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示