• 【算法学习笔记】59.链表 SJTU OJ 1368 丁姐的猴子


    Description

    丁姐和二哥一样养了很多猴子,每只猴子脖子上都挂着一个数字号码牌(数字可能重复但是不重要),一天他和这些猴子完游戏。一开始时有n只猴子围成一圈,猴子的号码牌按顺序为1~n。从当前猴子开始1~k报数,报到k后可能由两种操作:

    ①报到k的猴子从圈中出去,由刚刚退出的猴子的下一只猴子再开始报数。

    ②在报到k的猴子后边加一只号码牌为w的猴子,由刚刚加入的猴子开始再报数。

    初始时从编号为1的猴子开始报数,求最后圈内所有猴子的号码牌上数字之和。

    Input Format

    输入第一行两个数,分别为初始时的猴子数量n和操作数量m。

    接下来m行,每行描述一个操作:

    0 k,删除报到k的猴子。

    1 k w,在报到k的猴子后面加入一只号码牌为w的猴子。

    保证圈内至少有一只猴子。

    Output Format

    输出一行,一个数,表示圈内剩下猴子号码牌之和。

    Sample Input

    5 5
    0 2
    0 4
    1 1 10
    0 1
    1 2 3
    

    Sample Output

    15
    

    说明

    对于30%的数据,n<1000,m<1000

    对于100%的数据,n<10000, m<10000,w<100000

    对于每次操作链表中的元素为(括号里的是下一次报1的猴子):

    5 5 //[(1),2,3,4,5]
    0 2 //[1,(3),4,5]
    0 4 //[(3),4,5]
    1 1 10 //[3,(10),4,5]
    0 1//[3,(4),5]
    1 2 3//[3,4,5,(3)]

    因为会存在相同编号的猴子 所以必须要引入一个新的数组来存储id
    in函数少写了最后一行 导致一直没发现错误所在、、、有点傻

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    typedef unsigned long long ULL;
    
    
    int number[100000+10]; //下标是流水id 内容是身上的编号
    
    int front[100000+10];//流水id的操作
    int nex[100000+10];//流水id的操作
    //模拟法
    void out(int x){
        nex[front[x]] = nex[x];
        front[nex[x]] = front[x];
    }
    
    void in(int x,int w){ //此处的W指的是流水id
        nex[w] = nex[x];
        nex[x] = w;
        front[nex[w]] = w;
        front[w] = x;
    }
    
    int main(int argc, char const *argv[])
    {
        int M;//猴子的数量M
        int m; //操作的数量m
        cin>>M>>m;
        for (int i = 1; i <= M; ++i)
        {
            number[i] = i;//第i个猴子身上的编号是i
            front[i] = (i==1) ? M : i-1;
            nex[i] = (i==M) ? 1 : i+1;
        }
        int cur = 1;//接下来要报1的猴子编号
        int cnt = M;//还有多少只猴子
        int K;//数到K要进行操作
        ULL res = ((1+M)*M)/2;
        for (int i = 0; i < m; ++i)//m次操作
        {
            int flag;
            scanf("%d",&flag);
            if(flag==0){//要开始删除猴子
                scanf("%d",&K);
                K %= (cnt);
                if(K==0)    K+=cnt;
                for (int i = 0; i < K-1; ++i)
                    cur = nex[cur];//报数的过程
                out(cur);
                res -= number[cur];//减少剩余猴子所组成的编号之和
                cur = nex[cur];
                cnt--;//出去一只猴子
    
            }else{
                //不删除 只加入
                int W;
                scanf("%d %d",&K,&W);
                K %= (cnt);
                number[++M] = W;//流水ID
                if(K==0)    K+=cnt;
                for (int i = 0; i < K-1; ++i)
                    cur = nex[cur];//报数的过程
                in(cur,M);//cur的后面加入一个W
                res += W;
                cur = M;
                cnt++;//加入一只猴子
            }
     
        }
    
        cout<<res<<endl;
        return 0;
    }
    
    /*
    
    5 5
    0 2
    0 4
    1 1 10
    0 1
    1 2 3
    
    
    */
     


  • 相关阅读:
    java8 lambda表达式的使用
    关键字 static 静态
    关键字 enum 枚举
    关键字:final 最终的不可被改变的
    关键字 abstract 抽象
    Java中的关键字汇总(50个)
    关键字 assert 断言
    关键字 instanceof 实例
    java8新特性
    docker update restart=always container
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1368.html
Copyright © 2020-2023  润新知