1. 程式人生 > 其它 >C. Tokitsukaze and Two Colorful Tapes_並查集+環

C. Tokitsukaze and Two Colorful Tapes_並查集+環

C. Tokitsukaze and Two Colorful Tapes_並查集+環

題目大意

給ab兩個陣列,他們均是n的排列。現在要在滿足原來ai==bj的仍舊相等的條件下,重新排列ab,使得sum(abs(ai-bi))最大。

思路和程式碼

比較好看的就是這是一堆環。我們貪心的去給每個環一大一小的去分配數字即可。要注意其實奇數環和偶數環是一樣的。如下圖中只要把點5拿掉即可。

struct dsu{
	vct<int> fa ;
	dsu(int n){
		fa.resize(n + 1) ;
		rep(i , 0 , fa.size() - 1) fa[i] = i ;
	}
	int find(int u){
		return fa[u] == u ? u : find(fa[u]) ;
	}
	void merge(int u , int v){
		fa[find(u)] = find(v) ;
	}
};

int n , m , k ; 

void solve(){
	cin >> n ;
	dsu d(n) ;
	map<int , int> mp ;//維護環尺寸 
	vct<int> a(n + 1 , 0) ;
	vct<int> b(n + 1 , 0) ;
	rep(i , 1 , n) cin >> a[i] ;
	rep(i , 1 , n) cin >> b[i] ;
	rep(i , 1 , n) d.merge(a[i] , b[i]) ;
	
	rep(i , 1 , n) mp[d.find(i)] ++ ;
	
	ll ans = 0 ;
	vct<ll> p(n + 1 , 0) ;
	rep(i , 1 , n) p[i] = p[i - 1] + i ;
	ll l = 1 , r = n ;
	for(auto node : mp){
		int cnt = node.se ;
		if(cnt == 1) continue ;
//		cout << cnt << "\n" ;
		int l2 = l + cnt / 2 - 1 ;
		int r2 = r - cnt / 2 + 1 ;
		ans += 2 * ((p[r] - p[r2 - 1]) - (p[l2] - p[l - 1])) ;
		l = l2 + 1 , r = r2 - 1 ;
	}
	cout << ans << "\n" ;
	
}//code_by_tyrii 

小結

和這題很像

C. Where is the Pizza?_並查集 - tyrii