您的位置:首页 > 其它

Luogu1053 NOIP2005篝火晚会

2018-10-17 00:46 405 查看

  首先造出所要求的得到的环。如果将位置一一对应上,答案就是不在所要求位置的人数。因为显然这是个下界,并且脑补一下能构造出方案达到这个下界。

  剩下的问题是找到一种对应方案使错位数最少。可以暴力旋转这个环,然而是n2的。诶是不是特别熟悉……这好像很像卷积?然而好像没有什么优美的函数能方便的计算出两个排列的不匹配数,所以就别想NTT了。(是不是只有我这种弱智会往这上面想啊)

  应该可以类似暴力的移动开头利用偏移量之类的来计算,然而容易被绕晕。注意到每个人向右移动到目标位置的最少次数之间的关系是不变的,相同的总是相同不同的总是不同,直接统计即可。

  注意还可以将环翻转,需要再搞一次。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
#define N 50010
#define P 998244353
int n,a
,b
,q
,cnt[N<<1],ans=0;
bool flag
;
void solve()
{
memset(cnt,0,sizeof(cnt));
for (int i=1;i<=n;i++) cnt[(q[i]-i+n)%n]++;
for (int i=0;i<n;i++) ans=max(ans,cnt[i]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1053.in","r",stdin);
freopen("1053.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=1;i<=n;i++) a[i]=read(),b[i]=read();
int x=a[1],from=1;q[1]=1;flag[1]=1;
for (int i=2;i<=n;i++)
{
if (flag[x]) {cout<<-1;return 0;}
q[i]=x;flag[x]=1;
if (a[x]==from) from=x,x=b[x];
else if (b[x]==from) from=x,x=a[x];
else {cout<<-1;return 0;}
}
if (x!=1) {cout<<-1;return 0;}
solve();
reverse(q+1,q+n+1);
solve();
cout<<n-ans;
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: