博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[NOIp2005]篝火晚会
阅读量:6038 次
发布时间:2019-06-20

本文共 1407 字,大约阅读时间需要 4 分钟。

Description

Solution

首先要发现一个事实:对于每个不再正确位置上的人,我们都要花费1的代价来让他正确(然而我没有发现…)。

TODO:证明这个事实。

然后就可以转化问题为:最多有多少个人不用动。那么那些人不用动呢?就是那些与目标位置距离相等的人的集合,即断环为链之后,不用右移就在目标位置的人、右移一次到达目标位置的人、右移两次……这几群人。他们之中最多的那群就是最多有多少个人不用移动。

如何生成目标链呢?直接模拟就好了。不过要注意如果“我爱的人不爱我”的话就gg了。

Code

#include 
#include
const int N = 50010;int fr[N][2], per[N];int n;int spin[N];int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d%d", &fr[i][0], &fr[i][1]); // 计算完美的序列 for (int i = 1; i <= n; ++i) { if ((i != fr[fr[i][1]][0] && i != fr[fr[i][1]][1]) || (i != fr[fr[i][0]][0] && i != fr[fr[i][0]][1])) { puts("-1"); return 0; } } per[1] = 1; per[2] = fr[1][0]; per[n] = fr[1][1]; for (int i = 2; i < n; ++i) { if (per[i-1] == fr[per[i]][0]) { per[i+1] = fr[per[i]][1]; } else { per[i+1] = fr[per[i]][0]; } } // 由于我们恢复每个点的代价为1,所以找出哪些点不用动,剩下的就是答案。 int ans = 0x3f3f3f3f; for (int i = 1; i <= n; ++i) { if (++spin[(per[i] - i + n) % n] > n - ans) { ans = n - spin[(per[i] - i + n) % n]; } } memset(spin, 0, sizeof spin); for (int i = 1; i <= n; ++i) { if (++spin[(per[i] + i - 1) % n] > n - ans) { ans = n - spin[(per[i] + i - 1) % n]; } } printf("%d\n", ans); return 0;}

转载于:https://www.cnblogs.com/wyxwyx/p/noip20053.html

你可能感兴趣的文章
我的友情链接
查看>>
eclipse 3.7(indigo)在线汉化--最省事的方法
查看>>
我的友情链接
查看>>
java基础(五)集合/IO流/异常
查看>>
RabbitMq、ActiveMq、ZeroMq、kafka之间的比较
查看>>
二叉树的后序遍历 Binary Tree Postorder Traversal
查看>>
ansible学习笔记
查看>>
浅谈SMTP配置(邮件系统)
查看>>
Eclipse中jetty运行maven项目
查看>>
如何快速提高Ecshop二次开发效率
查看>>
我的友情链接
查看>>
C语言第二天(结构体)
查看>>
《python参考手册第二章》
查看>>
字符串子串
查看>>
我的友情链接
查看>>
正则表达式一
查看>>
基于Qt的OpenGL可编程管线学习(11)- 高斯模糊
查看>>
bochs compile 编译
查看>>
ClassLoader 原理
查看>>
我的友情链接
查看>>