[CSP-キャンパストレーニング] C

問題の意味

配置するように巻き数が最も少ないので、最適な戦略を求めて、第1の小Bの動作、ラウンド交換あたり既知の小Bの数、完全な配列に、二つの小さなA及びBテイクは、2つの数値を交換する一つの操作を小さな操作を回します注文した、\((N- \のLeq 10 ^ 5)\)

考え

;手ラビングはない操作の相関シーケンス、すなわちスイッチング動作ABとB二つの動作に、Aと、操作なし差(良好可能点線議論)見つからない
場合ので、二分法によって満たさを\(X \)時間が配列しますシーケンス、操作後にのみBにキャンセルする必要があるが、また、注文した
回答の半分は\(MID \) 最初の操作が再びBを実施し、その後、操作方法を考えます

交換は、順序付けられたシーケンスによって、カオス系列になって - >古典的な質問(なぜ私はqwq逆順ああだと思います)

すぐに\(私は\)がする\(a_iを\)にも側面が明らかにシンプルなリングを形成する、単純な答えは、すべてのリングN-(各リングの数は、互いに独立して、リングのニーズ(リングサイズ-1)還元工程のです)

コード

#include<bits/stdc++.h>
#define N 200005
#define lowbit(x) ((x)&(-(x)))
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
typedef long long ll;
int n,a[N],b[N],c[N],x[N<<1],y[N<<1];
bool vis[N];
template <class T>
void read(T &x)
{
    char c; int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
}
bool check(int mid)
{
    memset(vis,0,sizeof(vis));
    memset(c,0,sizeof(c));
    memcpy(b,a,sizeof(b));
    //b操作了之后才完成 
    for(int i=1;i<=mid;++i) swap(b[x[i]],b[y[i]]);
    int ans=0;
    for(int i=1;i<=n;++i)
    {
        if(!vis[i])
        {
            vis[i]=1;
            int x=b[i];
            while(!vis[x]) { vis[x]=1; x=b[x]; ++ans; }
        }
    }
    return ans<=mid;
}
int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    read(n);
    for(int i=1;i<=n;++i) read(a[i]),++a[i];
    for(int i=1,t=2*n;i<=t;++i) read(x[i]),read(y[i]),++x[i],++y[i];
    int l=0,r=2*n,ans=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/Chtholly/p/11799737.html