这次对劲了…
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) bi−bj,(1≤i,j≤n)
思路:
假设 b 1 , … , b n b_1,…,b_n b1,…,bn存在,那么题意即是对于 1 ≤ i ≤ n 1≤i≤n 1≤i≤n, 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=bji−bki.
考虑构造成一张 n n n个节点, m m m条边的有向图,其中每条边都是由 j i → k i j_i →k_i ji→ki
假定我们暂时忽视方向,将其看作一张边为 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 (bv1−bv2)+(bv2−bv3)+...+(bvm−bv1)=0,所以这张无向图是一个圆。
在这张图中,对于任意 i i i,都存在 1 ≤ t i ≤ n 1≤t_i≤n 1≤ti≤n满足:
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} bvi−bvi+1={ati−ati有向边vi→vi+1有向边vi←vi+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,…,tm与s1,…,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=bti−siati(1≤i<m)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=bj−bk
②:为了方便构造,我们使得 a i = b t i − b t i + 1 a_i = b_{t_i} - b_{t_{i + 1}} ai=bti−bti+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 (bv1−bv2)+(bv2−bv3)+...+(bvm−bv1)=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;
}