P1053 [NOIP2005 提高组] 篝火晚会
->( )可以不连续 + 移动 编号是 b1,b2.....
-> 相同数的个数最多的 可以通过 旋转 +圈可以反转移动
-> 其他的数可以 通过编号 连成一个圈 与原来的 圈一样
-> 构造圈+自己的语言做+翻译->count
! 圈的性质 ->反转+移动
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int Maxn=50010; int Dv1[Maxn],Dv2[Maxn]; //分别表示与1,2,...,n和n,n-1,...,2,1的差值 int vis[Maxn]; int c[Maxn];//目标链 int l1[Maxn],l2[Maxn]; int pd=1,n,ans=0; inline int read()//读入优化 { int fl=1,rt=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') fl=-1; ch=getchar();} while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0'; ch=getchar();} return fl*rt; } void Build()//建目标链 { c[1]=1; c[2]=l1[1]; vis[c[1]]=vis[c[2]]=1; for(int i=2;i<=n-1;i++) { if(c[i-1]==l1[c[i]]) c[i+1]=l2[c[i]],vis[c[i+1]]=1; else if(c[i-1]==l2[c[i]]) c[i+1]=l1[c[i]],vis[c[i+1]]=1; else { pd=0; printf("-1\n"); return ; } } for(int i=1;i<=n;i++) if(!vis[i]) pd=0,printf("-1\n"); //c[n] l1/l2 一定是 c[n-1] 且 c[n] l2/l1 一定是c[1] if((c[1]==l1[c[n]]&&c[n-1]!=l2[c[n]])||(c[1]!=l1[c[n]]&&c[n-1]==l2[c[n]])) pd=0,printf("-1\n"); else if((c[1]==l2[c[n]]&&c[n-1]!=l1[c[n]])||(c[1]!=l2[c[n]]&&c[n-1]==l1[c[n]])) pd=0,printf("-1\n"); } void count()//求答案 { for(int i=1;i<=n;i++) { Dv1[(c[i]-i+n)%n]++; Dv2[(c[n-i+1]-i+n)%n]++; } for(int i=0;i<=n-1;i++) ans=max(ans,max(Dv1[i],Dv2[i]));//最大的不用调整的数 printf("%d\n",n-ans);//cause 移动 编号是 b1,b2...bm 的位置 -> 任意-> } void read_ini() { n=read(); for(int i=1;i<=n;i++) l1[i]=read(),l2[i]=read(); Build(); if(pd) count(); } int main() { read_ini(); return 0; }

浙公网安备 33010602011771号