zoukankan      html  css  js  c++  java
  • UVA 12657 Boxes in a Line (双向链表)

    You have n boxes in a line on the table numbered 1: : : n from left to right. Your task is to simulate 4
    kinds of commands:
     1 X Y : move box X to the left to Y (ignore this if X is already the left of Y )
     2 X Y : move box X to the right to Y (ignore this if X is already the right of Y )
     3 X Y : swap box X and Y
     4: reverse the whole line.
    Commands are guaranteed to be valid, i.e. X will be not equal to Y .
    For example, if n = 6, after executing 1 1 4, the line becomes 2 3 1 4 5 6. Then after executing
    2 3 5, the line becomes 2 1 4 5 3 6. Then after executing 3 1 6, the line becomes 2 6 4 5 3 1.
    Then after executing 4, then line becomes 1 3 5 4 6 2
    Input
    There will be at most 10 test cases. Each test case begins with a line containing 2 integers n, m
    (1  n; m  100;000). Each of the following m lines contain a command.
    Output
    For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n
    from left to right.
    Sample Input
    6 4
    1 1 4
    2 3 5
    3 1 6
    4
    6 3
    1 1 4
    2 3 5
    3 1 6
    100000 1
    4
    Sample Output
    Case 1: 12
    Case 2: 9
    Case 3: 2500050000

    题意:有一行盒子,从左到右一次编号为1,2,3,......n,可以执行四种命令:

    1 X Y 把X移到Y左边(如果X已经在Y左边,则忽略)

    2 X Y 把X移到Y右边(如果X已经在Y右边,则忽略)

    3 X Y 交换X和Y的位置

    4 翻转整条链

    经过M次变换后,求整条链奇数位的和

    分析:当初想通过分奇偶数情况,用前缀和还有整体操作来求解,但是后来发现数据操作的那个部分很不好写,所以用双向链表,这也是算法竞赛入门经典(第二版)的题目P144

    通过left数组和right数组和link函数实现两个节点的连接,这里的Link函数很巧妙。

    这题要注意因为4操作会对1操作和2操作进行改变,所以设置一个 inv ,最后输出的时候,也会有影响。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<string>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<map>
    #include<stdlib.h>
    #include<algorithm>
    #define LL __int64
    #define FIN freopen("in.txt","r",stdin)
    using namespace std;
    const int MAXN=100000+5;
    int l[MAXN],r[MAXN];
    int n,m;
    void link(int L,int R)  //连接两个节点的link函数
    {
        l[R]=L;
        r[L]=R;
    }
    int main()
    {
        int Case=0;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                l[i]=i-1;
                r[i]=(i+1)%(n+1);
            }
            l[0]=n;
            r[0]=1;
            int inv=0,opt,X,Y;
            while(m--)
            {
                scanf("%d",&opt);
                if(opt==4) inv=!inv;
                else
                {
                    scanf("%d %d",&X,&Y);
                    if(opt==3 && r[Y]==X) swap(X,Y); //这里要注意一下,并不是交换了X,Y的位置,而是交换了X,Y的值,以便后面进行统一处理
                    if(opt!=3 && inv) opt=3-opt;  //这里可以看成从后往前处理
                    if(opt==1 && l[Y]==X) continue;
                    if(opt==2 && r[Y]==X) continue;
    
                    int LX=l[X],RX=r[X],LY=l[Y],RY=r[Y];
                    if(opt==1)
                    {
                        link(LX,RX);
                        link(LY,X);
                        link(X,Y);
                    }
                    if(opt==2)
                    {
                        link(LX,RX);
                        link(Y,X);
                        link(X,RY);
                    }
                    if(opt==3)
                    {
                        if(r[X]==Y)
                        {
                            link(LX,Y);
                            link(Y,X);
                            link(X,RY);
                        }
                        else
                        {
                            link(LX,Y);
                            link(Y,RX);
                            link(LY,X);
                            link(X,RY);
                        }
                    }
                }
            }
            long long ans=0;  //注意最后结果可能会很大
            int b=0;
            for(int i=1;i<=n;i++)
            {
                b=r[b];
                if(i%2==1) ans+=b;
            }
            if(inv && n%2==0) ans=(long long)(n+1)*n/2-ans; //长度为偶数,翻转后所有数的总和减去偶数项的和
            printf("Case %d: %lld
    ",++Case,ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【转】Redis和Memcache对比及选择
    Ubuntu下php环境的搭建
    【HTML和CSS】总结
    【python】 The different between ' %r ' and ' %s '
    Learn Python The Hard Way
    Vim 插件配置及快捷键
    sublime-text 插件配置
    mysql-5.7在CentOS-7下的rpm安装
    oracle pdb基本管理
    Oracle 12cR2 Installation On CentOS-7
  • 原文地址:https://www.cnblogs.com/clliff/p/4738564.html
Copyright © 2011-2022 走看看