CF1677C Tokitsukaze and Two Colorful Tapes(置换转环赋值差的和最大)
I_am_Accepted · · 题解
Analysis
将一个位置看成两个色带对应位置颜色之间的边。
这样我们得到了一张
我们要给每个点赋值
若一个点的权值小于两边,则称为「山谷」;若一个点的权值大于两边,则称为「山峰」;剩下的为「山坡」。显然山峰与山谷个数相同。
我们用另一种方式算边权和:设山峰的点权和为
由于山坡对答案没贡献,我们尽量多山峰(
设这样算出来山峰最多
所以我们将山峰们设为最大的值
答案也就呼之欲出:
Code
//Said no more counting dollars. We'll be counting stars.
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Rof(i,j,k) for(int i=j;i>=k;i--)
#define int long long
#define N 100010
int n,a[N],b[N],ans;
bool vis[N];
int dfs(int x){
vis[x]=1;
if(vis[b[x]]) return 1;
else return 1+dfs(b[x]);
}
void work(){
cin>>n;
int x;
For(i,1,n){
cin>>x;
a[x]=i;
}
For(i,1,n){
cin>>x;
b[i]=a[x];
}
ans=0;
For(i,1,n) vis[i]=0;
For(i,1,n) if(!vis[i]) ans+=dfs(i)>>1;
cout<<2*ans*(n-ans)<<endl;
}
signed main(){IOS;
int T;cin>>T;
while(T--)work();
return 0;}