Codeforces Global Round 20 D F1 F2/more

https://codeforc.es/contest/1672

F1

https://www.luogu.com.cn/blog/AlexWei/solution-cf1672f1

  1. 将置换分解为若干轮换(环),悲伤值越大 \(\Rightarrow\) 环越少(设环为 \(k\) 个,一个环只需要交换 \(sz-1\) 次,所以总共交换 \(n-k\) 次,显然环越少,悲伤值越大)

  2. 根据其置换的最优性,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 个数要交换到哪里,由于这两个元素一样,所以并不会影响正确性。由于环更多了,显然会成这样。得证。

  3. 根据 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

image

#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

image

很奇妙的题目,比 F 难多了!

posted @ 2022-11-03 21:43  FxorG  阅读(32)  评论(0编辑  收藏  举报