Codeforces Global Round 15(A-D)

这次对劲了…
在这里插入图片描述在这里插入图片描述

A. Subsequence Permutation

题意:对于一个字符串,需要对哪些位置进行排序,使得整体有序

思路:直接排序再对比即可

代码

#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 1e6 + 10;
char s[N], f[N];
inline void solve() {
    int n; cin >> n;
    for(int i = 0; i < n; i++) cin >> s[i],f[i] = s[i];
    sort(s, s + n);
    int ans = 0;
    for(int i = 0; i < n; i++) {
        if(f[i] != s[i]) ans++;
    }
    cout << ans << endl;
    return ;
}
signed main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

B. Running for Gold

题意:给定了n个人各自5场的比赛排名,如果A至少有三场比B好,那么就说明A比B牛逼,求最牛逼的那个人的编号

思路:第一次找到一个牛逼的,然后再和除了他之外的人再比较一下,如果最牛逼称号易主了,说明不行,否则行

代码

#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 1e6 + 10;
int x[N][10];
inline void solve() {
    int n; cin >> n;
    for(int i = 1; i <= n; i++) for(int j = 1; j <= 5; j++) cin >> x[i][j];
    int win1 = 1;
    for(int i = 2; i <= n; i++) {
        int cnt = 0;
        for(int j = 1; j <= 5; j++) {
            if(x[win1][j] < x[i][j]) cnt++;
        }
        if(cnt < 3) win1 = i;
    }
    int win2 = win1;
    for(int i = win1 + 1; i <= n; i++) {
        int cnt = 0;
        for(int j = 1; j <= 5; j++) {
            if(x[win2][j] < x[i][j]) cnt++;
        }
        if(cnt < 3) win2 = i;
    }
    for(int i = 1; i < win1; i++) {
        int cnt = 0;
        for(int j = 1; j <= 5; j++) {
            if(x[win2][j] < x[i][j]) cnt++;
        }
        if(cnt < 3) win2 = i;
    }
    if(win1 == win2) cout << win1 << endl;
    else cout << -1 << endl;
    return ;
}
signed main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

C - Maximize the Intersections

题意:被抬的,还在想…

思路:

代码

#include <bits/stdc++.h>
using namespace std;
vector<int> fff;
int dist[101000];
int ok[1010000];
int T,n,m,a,b;
inline void solve() {
	cin >> n >> m;
	fff.clear(); memset(ok, 0, sizeof ok);
	for(int i = 1; i <= m; i++) {
		cin >> a >> b;
		if(b < a) swap(a, b);
		ok[a] = ok[b] = 1;
		dist[a] = b;
		dist[b] = a;
	}
	int cnt = 0;
	for(int i = 1; i <= n * 2; i++)
		if(ok[i] == 0)
			fff.push_back(i);
	for(int i = 0; i < n - m; i++) {
		dist[fff[i]] = fff[i + n - m];
		dist[fff[i + n - m]] = fff[i];
	}
	int ans = 0;
	for(int i = 1; i <= 2 * n; i++)
		if(dist[i] < i)
			for(int j = dist[i] + 1; j < i; j++)
				if(dist[j] > i)
					ans ++;
	printf("%d\n",ans);
	return ;
}
int main() {

	cin >> T;
	while(T--) solve();
	return 0;
}

D - Array Differentiation

题意:对于一个数字序列A,判断是否存在数字序列B,满足任意 a i a_i ai = b i − b j , ( 1 ≤ i , j ≤ n ) b_i - b_j,(1≤i,j≤n) bibj,(1i,jn)

思路
假设 b 1 , … , b n b_1,…,b_n b1,,bn存在,那么题意即是对于 1 ≤ i ≤ n 1≤i≤n 1in j i , k i j_i,k_i ji,ki作为 b b b数组的下标,使得 a i = b j i − b k i a_i = b_{j_{i}} - b_{k_i} ai=bjibki.

考虑构造成一张 n n n个节点, m m m条边的有向图,其中每条边都是由 j i → k i j_i →k_i jiki

假定我们暂时忽视方向,将其看作一张边为 a i a_i ai,顶点数为 m m m,顶点编号为 v 1 , … , v m v_1,…,v_m v1,,vm的一张无向图,由于 ( b v 1 − b v 2 ) + ( b v 2 − b v 3 ) + . . . + ( b v m − b v 1 ) = 0 (b_{v_1} - b_{v_2}) + (b_{v_2} - b_{v_3}) + ... + (b_{v_m} - b_{v_1}) = 0 (bv1bv2)+(bv2bv3)+...+(bvmbv1)=0,所以这张无向图是一个圆。

在这张图中,对于任意 i i i,都存在 1 ≤ t i ≤ n 1≤t_i≤n 1tin满足:
b v i − b v i + 1 = { a t i 有向边 v i → v i + 1 − a t i 有向边 v i ← v i + 1 b_{v_i} - b _{v_i+1} = \begin{cases} a_{t_i}& \text{有向边}v_i→v_{i+1}\\ -a_{t_i}& \text{有向边}v_i←v_{i+1} \end{cases} bvibvi+1={atiati有向边vivi+1有向边vivi+1
因此我们需要构造一个集合 { t 1 , … , t m } ⊆ { 1 , … , n } \{t_1,…,t_m\} \subseteq\{1,…,n\} {t1,,tm}{1,,n}并且选用 m m m个符号 { s 1 , … , s m } ( s i ) ∈ { + 1 , − 1 } \{s_1,…,s_m\}(s_i)\in\{+1,-1\} {s1,,sm}(si){+1,1}满足
s 1 a t 1 + … + s 2 a t m = 0                     ( ※ ) s_1 a_{t_1} + … + s_2 a_{tm} = 0{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}{\,}(※) s1at1++s2atm=0
而这一条件也是 b b b数组存在的充分必要条件
m , t 1 , … , t m 与 s 1 , … , s m m,t_1,…,t_m与s_1,…,s_m m,t1,,tms1,,sm使得(※)存在时,我们通过以下方式构造出 b b b数组
{ b t 1 = 0 b t i + 1 = b t i − s i a t i ( 1 ≤ i < m ) b i = a i ( i ∉ { t 1 , … , t m } ) \begin{cases} b_{t_1} = 0& \text{}\\ b_{t_{i+1}} = b_{t_i} - s_i a_{t_i}(1≤i<m)\\ b_i = a_i(i \notin\{t_1,…,t_m\}) \end{cases} bt1=0bti+1=btisiati(1im)bi=ai(i/{t1,,tm})
再总结一下:
①:将问题抽象为一张包含了 n n n个点 n n n条边 { j , k } \{j, k\} {j,k}的有向图,其中 a i = b j − b k a_i = b_j - b_k ai=bjbk
②:为了方便构造,我们使得 a i = b t i − b t i + 1 a_i = b_{t_i} - b_{t_{i + 1}} ai=btibti+1,如果将 b b b数组的下标作为图上的节点,假设 b b b数组形成的环的长度为 m m m,那么我们可以得到这样一个式子:
( b v 1 − b v 2 ) + ( b v 2 − b v 3 ) + . . . + ( b v m − b v 1 ) = 0 (b_{v_1} - b_{v_2}) + (b_{v_2} - b_{v_3}) + ... + (b_{v_m} - b_{v_1}) = 0 (bv1bv2)+(bv2bv3)+...+(bvmbv1)=0
③:

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, x[11];
unordered_map<int, int> ok;
inline void find(int i , int sum) {
	if(i > n) {
		ok[sum]++;
		return ;
	}
	find(i + 1, sum);
	find(i + 1, sum + x[i]);
	return ;
}
inline void solve() {
	cin >> n;
	for(int i = 1; i <= n; i ++) 
		cin >> x[i];
	ok.clear();
	find(1, 0);
	int flag = 0;
	for(auto i : ok) 
		if(i.second >= 2) 
			flag = 1;
	if(flag == 1) cout << "YES" << endl;
	else cout << "NO" << endl;
	return ;
}
signed main() {
	ios::sync_with_stdio(false); cin.tie(0);
	int T; cin >> T;
	while(T --) solve();
	return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

顶白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值