Codeforces LATOKEN Round 1 (Div. 1 + Div. 2)

这次打的好差…暴露出了交互题和图论的知识点不熟悉,还有对题目的思考不够简洁


A. Colour the Flag

Today we will be playing a red and white colouring game (no, this is not the Russian Civil War; these are just the colours of the Canadian flag).

You are given an n×m grid of “R”, “W”, and “.” characters. “R” is red, “W” is white and “.” is blank. The neighbours of a cell are those that share an edge with it (those that only share a corner do not count).

Your job is to colour the blank cells red or white so that every red cell only has white neighbours (and no red ones) and every white cell only has red neighbours (and no white ones). You are not allowed to recolour already coloured cells.

Input
The first line contains t (1≤t≤100), the number of test cases.

In each test case, the first line will contain n (1≤n≤50) and m (1≤m≤50), the height and width of the grid respectively.

The next n lines will contain the grid. Each character of the grid is either ‘R’, ‘W’, or ‘.’.

Output
For each test case, output “YES” if there is a valid grid or “NO” if there is not.

If there is, output the grid on the next n lines. If there are multiple answers, print any.

In the output, the "YES"s and "NO"s are case-insensitive, meaning that outputs such as “yEs” and “nO” are valid. However, the grid is case-sensitive.

  • 思路:由于满足情况的棋盘只有两种情况:

    • 第一种:
    RWR
    WRW
    RWR
    • 第二种:
    WRW
    RWR
    WRW
    • 可以发现其中存在一个规律就是字符R或者字符W所在的格子的横纵坐标之和为奇数或偶数。
    • 最最核心的思想就是,输出棋盘是哪个类型的,但由于存在“.”的情况,所以我们不能直接判断是哪种类型,于是我们采取先判断它不是哪种类型的,再输出另外的类型。
    • 如判断不是A类型的,我们输出B类型
    • 代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
   ios::sync_with_stdio(false); cin.tie(0);
   int t, n, m;
   char s[55][55];
   cin >> t;
   while(t--) {
   	cin >> n >> m;
   	for(int i = 1; i <= n; i++)
   		for(int j = 1; j <= m; j++)
   			cin >> s[i][j];
   	bool found = false;
   	for(int r = 0; r < 2; r++) {
   		bool flag = true;
   		for(int i = 1; i <= n; i++) {
   			for(int j = 1; j <= m; j++) {
   				char now = (i + j + r) % 2 == 0 ? 'R' : 'W';
   				if(s[i][j] == now) {
   					flag = false;
   					break;
   				}
   			}
   		}
   		if(flag) {
   			cout << "YES\n";
   			for(int i = 1; i <= n; i++) {
   				for(int j = 1; j <= m; j++) {
   					char now = (i + j + r + 1) % 2 == 0 ? 'R' : 'W';
   					cout << now;
   				}
   				cout << "\n";
   			}
   			found = true;
   			break;
   		}
   	}
   	if(!found) {
   		cout << "NO\n";
   	}
   }
   return 0;
} 

B. Histogram Ugliness

Little Dormi received a histogram with n bars of height a1,a2,…,an for Christmas. However, the more he played with his new histogram, the more he realized its imperfections, so today he wanted to modify it to his liking.

To modify the histogram, Little Dormi is able to perform the following operation an arbitrary number of times:

Select an index i (1≤i≤n) where ai>0, and assign ai:=ai−1.
Little Dormi defines the ugliness score of his histogram (after performing some number of operations) as the sum of the vertical length of its outline and the number of operations he performed on it. And to make the histogram as perfect as possible, he would like to minimize the ugliness score after modifying it with some number of operations.

However, as his histogram is very large, Little Dormi is having trouble minimizing the ugliness score, so as Little Dormi’s older brother, help him find the minimal ugliness.

Consider the following example where the histogram has 4 columns of heights 4,8,9,6:


The blue region represents the histogram, and the red lines represent the vertical portion of the outline. Currently, the vertical length of the outline is 4+4+1+3+6=18, so if Little Dormi does not modify the histogram at all, the ugliness would be 18.

However, Little Dormi can apply the operation once on column 2 and twice on column 3, resulting in a histogram with heights 4,7,7,6:


Now, as the total vertical length of the outline (red lines) is 4+3+1+6=14, the ugliness is 14+3=17 dollars. It can be proven that this is optimal.

Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). Description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤4⋅105).

The second line of each test case contains n integers a1,a2,…,an (0≤ai≤109).

It is guaranteed that the sum of n over all test cases does not exceed 4⋅105.

Output
For each test case output one integer, the minimal ugliness Little Dormi can achieve with the histogram in that test case.

  • 思路:首先想到对于每一个比相邻两边都高的长方形,每一次降低,都是减少两次贡献(左右),所以我们就应该把每一个比相邻两边都高的长方形都往下降低到相邻两边的最高点。
  • 代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 10;
ll t, n, m, x[N];
inline void solve() {
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> x[i];
	x[0] = 0; x[n + 1] = 0;
	ll ans = 0;
	for(int i = 1; i <= n + 1; i++) {
		ans += abs(x[i] - x[i - 1]);
	}
	for(int i = 1; i <= n; i++) {
		if(x[i] > max(x[i - 1], x[i + 1])) {
			ans -= x[i] - max(x[i - 1], x[i + 1]);
		}
	}
	cout << ans << endl;
	return ;
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		solve();
	}
	return 0;
} 

C

When he’s not training for IOI, Little Alawn enjoys playing with puzzles of various types to stimulate his brain. Today, he’s playing with a puzzle that consists of a 2×n grid where each row is a permutation of the numbers 1,2,3,…,n.

The goal of Little Alawn’s puzzle is to make sure no numbers on the same column or row are the same (we’ll call this state of the puzzle as solved), and to achieve this he is able to swap the numbers in any column. However, after solving the puzzle many times, Little Alawn got bored and began wondering about the number of possible solved configurations of the puzzle he could achieve from an initial solved configuration only by swapping numbers in a column.

Unfortunately, Little Alawn got stuck while trying to solve this harder problem, so he was wondering if you could help him with it. Find the answer modulo 109+7.

Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). Description of the test cases follows.

The first line of each test case contains a single integer n (2≤n≤4⋅105).

The next two lines of each test case describe the initial state of the puzzle grid. Each line will be a permutation of the numbers 1,2,3,…,n and the numbers in each column and row will be pairwise distinct.

It is guaranteed that the sum of n over all test cases does not exceed 4⋅105.

Output
For each test case output a single integer, the number of possible solved configurations of the puzzle Little Alawn can achieve from an initial solved configuration only by swapping numbers in a column. As the answer can be very large, please output it modulo 109+7.

The answer for each test case should be on a separate line.

  • 这个题太奇妙了!第一次遇到这种思路的!!!!
  • 首先,我们确定一个事实,就是当其中一列变化的时候,与它相关联的列都要发生改变。
  • 然后我们可以构造一个简单的有向图,其中的边为ai -> bi,这样会形成一些连通分量,那么每一次我们改变一列时,就是相当于改变了这列形成的边的方向,而所有的与它相关联的列都会发生改变,则是相当于这条边所在的连通分量内的所有边都要反向。
  • 综上,我们的大致思路就出来了,先找到连通分量的块数k,每一个连通分量的变化都只有两种,于是答案就是2^k
  • 代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 10, mod = 1e9 + 7;
ll t, n, m, x[N], y[N], p[N];
inline ll find(ll xx) {
	if(xx != p[xx]) p[xx] = find(p[xx]);
	return p[xx];
}
inline void merge(ll xx, ll yy) {
	xx = find(xx); yy = find(yy);
	if(xx != yy) {
		p[xx] = yy;
	}
	return ;
}
inline ll q_pow(ll b, ll p, ll k) {
	ll ans = 1;
	while(p > 0) {
		if(p&1)	ans=b*ans%k;
		b=b*b%k;
		p=p>>1;
	}
	return ans%k;
}
inline void solve() {
	cin >> n;
	for(int i = 1; i <= n; i++) p[i] = i;
	for(int i = 1; i <= n; i++) cin >> x[i];
	for(int i = 1; i <= n; i++) cin >> y[i];
	for(int i = 1; i <= n; i++)
		merge(x[i], y[i]);
	unordered_map<ll, ll> vis;
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		ll ok = find(i);
		if(vis[ok] == 0) {
			vis[ok] = 1;
			ans++;
		}
	}
	cout << q_pow(2, ans, mod) << endl;
	return ;
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		solve();
	}
	return 0;
} 

D

This is an interactive problem.

Little Dormi was faced with an awkward problem at the carnival: he has to guess the edges of an unweighted tree of n nodes! The nodes of the tree are numbered from 1 to n.

The game master only allows him to ask one type of question:

Little Dormi picks a node r (1≤r≤n), and the game master will reply with an array d1,d2,…,dn, where di is the length of the shortest path from node r to i, for all 1≤i≤n.
Additionally, to make the game unfair challenge Little Dormi the game master will allow at most ⌈n2⌉ questions, where ⌈x⌉ denotes the smallest integer greater than or equal to x.

Faced with the stomach-churning possibility of not being able to guess the tree, Little Dormi needs your help to devise a winning strategy!

Note that the game master creates the tree before the game starts, and does not change it during the game.

Input
The first line of input contains the integer n (2≤n≤2000), the number of nodes in the tree.

You will then begin interaction.

Output
When your program has found the tree, first output a line consisting of a single “!” followed by n−1 lines each with two space separated integers a and b, denoting an edge connecting nodes a and b (1≤a,b≤n). Once you are done, terminate your program normally immediately after flushing the output stream.

You may output the edges in any order and an edge (a,b) is considered the same as an edge (b,a). Answering is not considered as a query.

Interaction
After taking input, you may make at most ⌈n2⌉ queries. Each query is made in the format “? r”, where r is an integer 1≤r≤n that denotes the node you want to pick for that query.

You will then receive n space separated integers d1,d2,…,dn, where di is the length of the shortest path from node r to i, followed by a newline.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

fflush(stdout) or cout.flush() in C++;
System.out.flush() in Java;
flush(output) in Pascal;
stdout.flush() in Python;
see documentation for other languages.
If at any point you make an invalid query or try to make more than ⌈n2⌉ queries, the interaction will terminate immediately and you will receive a Wrong Answer verdict.

Hacks

To hack a solution, use the following format.

The first line contains the integer n (2≤n≤2000).

The next n−1 lines contain two integers u and v (1≤u,v≤n) denoting an edge between u and v (u≠v). These n−1 edges must form a tree.

  • 好的,终于来到丧尽天良的D题了,TMD,这么简单一道题,我没有写出来,吐了,错失上分的机会淦,先放个提交截图吧,感受一下我当时的心情…嗯没法粘贴,反正就是一个半小时全浪费在这傻逼题上了。
  • 直接先问一个点,然后由这个点分层次,以离他的距离为奇数偶数来分类好吧,然后遍历包含点数最少的那个,注意第一次访问的点不要放进分类中,有可能会卡n/2 + 1,思路就出来了好吧,艹
  • 噢还有几个小技巧:
    • 1.用set<pair<int, int> > ans;来存,可以避免输出重复的边
    • 2.minmax(a, b),使得a为a,b中的最小值,b为最大值
  • 代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	ll n; cin >> n;
	set<pii> s;
	set<ll> a, b;
	cout << "? " << 1 << endl;
	for(int i = 1; i <= n; i++) {
		ll x; cin >> x;
		if(x == 0) continue;
		if(x == 1) s.insert({1, i});
		if(x & 1) a.insert(i);
		else b.insert(i); 
	}
	if(a.size() > b.size()) swap(a, b);
	for(auto i : a) {
		cout << "? " << i << endl;
		for(ll j = 1; j <= n; j++) {
			ll x; cin >> x;
			if(x == 1) s.insert({minmax(i, j)});
		}
	}
	cout << "!\n";
	for(auto i : s) cout << i.first << " " << i.second << endl;
	return 0;
} 
  • 超级短的是不是,tmd当时真的是傻逼了…

好了没了,你当我啥水平还能继续补下去…下次加油吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顶白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值