zoukankan      html  css  js  c++  java
  • [Noip2005] 篝火晚会

    题目描述

    佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有nnn个同学,编号从111到nnn。一开始,同学们按照1,2,…,n1,2,…,n1,2,,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。

    佳佳可向同学们下达命令,每一个命令的形式如下:

    (b1,b2,...bm−1,bm)(b_1, b_2,... b_{m-1}, b_m)(b1,b2,...bm1,bm)

    这里mmm的值是由佳佳决定的,每次命令mmm的值都可以不同。这个命令的作用是移动编号是b1,b2,…,bmb_1,b_2,…, b_mb1,b2,,bm的这m个同学的位置。要求b1b_1b1换到b2b_2b2的位置上,b2b_2b2换到b3b_3b3的位置上,……,要求bmb_mbm换到b1b_1b1的位置上。执行每个命令都需要一些代价。我们假定如果一个命令要移动mmm个人的位置,那么这个命令的代价就是mmm。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?

    输入输出格式

    输入格式:

    第一行是一个整数n(3≤n≤50000)n(3 le n le 50000)n(3n50000),表示一共有nnn个同学。

    其后nnn行每行包括222个不同的正整数,以一个空格隔开,分别表示编号是111的同学最希望相邻的两个同学的编号,编号是222的同学最希望相邻的两个同学的编号,……,编号是nnn的同学最希望相邻的两个同学的编号。

    输出格式:

    一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出−1-11。

    输入输出样例

    输入样例#1: 复制
    4
    3 4
    4 3
    1 2
    1 2
    
    输出样例#1: 复制
    2

    说明

    对于30%的数据,n≤1000n le 1000n1000;
    对于全部的数据,n≤50000n le 50000n50000。

    2005提高组第三题

     

     
    又被Noip题吊打了。
    可以看出最小代价等于不在应该在的位置上的数的个数的最小值。
    于是我们可以枚举开始位置,还有两个方向,枚举结束时的目标环,求出不在应该在的位置上的数的最小个数就是答案。
    但是这样是$large O(N^2)$的会T,所以找规律。
    我们固定起始序列,任取一个目标序列,求出每一个位置到它应该到的位置的步数,发现,不管目标序列是什么样子,相同的就一直相同,不同的就一直不同。
    所以我们把答案变成n-最多的不用动的数量。
    然后发现其实距离应到的位置距离相同的最大的数量, 就是最多不用动的数量。
    所以这样就可以$large O(N)$求出。
    记得正反都跑一遍。
     

     
    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    #define reg register 
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 50005
    int n;
    int deg[N], ch[N][2];
    int L[N], R[N];
    int cnt[2][N];
    int a[N];
    
    int main() 
    {
        n = read();
        for (reg int i = 1 ; i <= n ; i ++)
        {
            ch[i][0] = read(), ch[i][1] = read();
            deg[ch[i][0]]++, deg[ch[i][1]]++;
        }
        for (reg int i = 1 ; i <= n ; i ++) if (deg[i] != 2) return puts("-1"), 0;
        int p = 1, num = 0;
        L[1] = ch[1][0], R[1] = ch[1][1];
        do {
            int y = R[p];
            L[y] = p, R[y] = ch[y][0] == p ? ch[y][1] : ch[y][0];
            p = y;
            num++;
        }while(p != 1);
        if (num != n) return puts("-1"), 0;
        p = 1;
        for (reg int i = 1 ; i <= n ; i ++, p = R[p]) 
            cnt[0][(i-p+n)%n]++;
        p = 1;
        for (reg int i = 1 ; i <= n ; i ++, p = L[p]) 
            cnt[1][(i-p+n)%n]++;
        int ans = 0;
        for (reg int i = 0 ; i < n ; i ++)
            ans = max(ans, max(cnt[0][i], cnt[1][i]));
        printf("%d
    ", n - ans);
        return 0;
    }
  • 相关阅读:
    Verilog学习笔记基本语法篇(七)········ 生成块
    Verilog学习笔记基本语法篇(六)········ 循环语句
    Verilog学习笔记基本语法篇(五)········ 条件语句
    Verilog学习笔记基本语法篇(四)·········块语句
    Verilog学习笔记基本语法篇(三)·········赋值语句(待补充)
    Verilog学习笔记基本语法篇(二)·········运算符
    Verilog学习笔记基本语法篇(一)·········数据类型
    甲乙类功率放大电路介绍及特点
    JVM虚拟机系列(二)虚拟机的逻辑结构
    JVM虚拟机系列(一)类的加载
  • 原文地址:https://www.cnblogs.com/BriMon/p/9579465.html
Copyright © 2011-2022 走看看