Codeforces Global Round 20 D F1 F2/more
https://codeforc.es/contest/1672
F1
https://www.luogu.com.cn/blog/AlexWei/solution-cf1672f1
-
将置换分解为若干轮换(环),悲伤值越大 \(\Rightarrow\) 环越少(设环为 \(k\) 个,一个环只需要交换 \(sz-1\) 次,所以总共交换 \(n-k\) 次,显然环越少,悲伤值越大)
-
根据其置换的最优性,2 个相同的元素不可能同时出现在一个环。
考虑 \(p_1\to p_2\to ... \to p_i\to p_{i+1}\to ... \to p_j \to p_{j+1}\to ... \to p_1\),其中 \(p_i\) 与 \(p_j\) 的权值相等。显然可以拆成 2 个环,\(p_1\to p_2\to ... \to p_i \to p_j+1\to p_1\),\(p_{i+1}\to ... \to p_j \to p_{i+1}\) 这一部分是因为你交换 2 个数要交换到哪里,由于这两个元素一样,所以并不会影响正确性。由于环更多了,显然会成这样。得证。 -
根据 2,显然环的下界个数是 \(mx\) 个,\(mx\) 为众数出现次数。
于是把众数的元素分到每一个环即可。
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(2e5+5);
//pair<int,int>vec[N];
map<int,vector<int> >mp;
int n,a[N],ct[N],vec[N];
void sol() {
mp.clear();
cin>>n; int mx=0,mxv=0;
for(int i=1;i<=n;i++) {
cin>>a[i]; ++ct[a[i]];
if(ct[a[i]]>mxv) mx=a[i],mxv=ct[a[i]];
}
for(int i=1;i<=n;i++) {
// if(a[i]!=mx) {
mp[a[i]].pb(i);
// }
}
for(int i=0;i<mxv;i++) {
int tot=0;
vec[++tot]=mp[mx][i];
for(auto it=mp.begin();it!=mp.end();) {
// cout<<i<<'\n';
if((*it).first==mx) {
++it; continue ;
}
vec[++tot]=(*it).second.back();
(*it).second.pop_back();
if((*it).second.empty()) {
mp.erase(it++);
} else ++it;
}
int qwq=a[vec[tot]];
for(int j=tot-1;j>=1;j--) {
a[vec[j+1]]=a[vec[j]];
}
a[vec[1]]=qwq;
}
for(int i=1;i<=n;i++) ct[a[i]]=0;
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<'\n';
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) sol();
return 0;
}
F2
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(4e5+5);
bool vis[N];
int n,a[N],b[N],dfn[N],low[N],ct[N],fir[N],tjtot;
bool ok;
vector<int>st,vec[N],g[N];
void tarjan(int x) {
dfn[x]=low[x]=++tjtot;
vis[x]=1; st.pb(x);
for(int y:g[x]) {
if(!dfn[y]) {
tarjan(y);
low[x]=min(low[x],low[y]);
} else if(vis[y]) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]) {
int qwq=0,sz=0;
while(1) {
qwq=st.back(); st.pop_back(); ++sz; vis[qwq]=0;
if(qwq==x) break ;
}
if(sz>1) {
ok=0; return ;
}
}
}
void sol() {
cin>>n; tjtot=0; ok=1;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
int mxv=0,mx=0;
for(int i=1;i<=n;i++) {
++ct[b[i]];
if(ct[b[i]]>mxv) mxv=ct[b[i]],mx=b[i];
}
for(int i=1;i<=n;i++) vec[a[i]].pb(i);
int tot=n;
for(int i=1;i<=n;i++) {
if(b[i]==mx) continue ;
if(fir[b[i]]) {
g[i].pb(fir[b[i]]); continue ;
}
fir[b[i]]=++tot;
g[i].pb(fir[b[i]]);
for(int x:vec[b[i]]) g[fir[b[i]]].pb(x);
}
for(int i=1;i<=tot;i++) {
if(!dfn[i]) {
while(!st.empty()) st.pop_back();
tarjan(i);
}
}
for(int i=1;i<=n;i++) ct[b[i]]=fir[b[i]]=0,vec[a[i]].clear();
for(int i=1;i<=tot;i++) g[i].clear(),low[i]=dfn[i]=vis[i]=0;
if(ok) {
cout<<"AC\n";
} else cout<<"WA\n";
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) sol();
return 0;
}
D
很奇妙的题目,比 F 难多了!