zoukankan      html  css  js  c++  java
  • UVA 12657 Boxes in a Line

    题目链接:https://uva.onlinejudge.org/index.php?

    option=com_onlinejudge&Itemid=8&page=show_problem&problem=4395




    题目意思是说,给出一个数n。表示存在一个整数序列1……n,然后进行四种操作:

    操作一:输入x,y。表示将x移到y的左边(若x本来就在y的左边则忽略)。

    操作二:输入x,y。表示将x移到y的右边(若x本来就在y的右边则忽略);

    操作三:输入x,y。表示交换x和y。

    操作四:将整个序列倒置。

    最后要求的是操作后的整个序列奇数项的和。

    数据为100000。直接模拟肯定超时。用STL的链表也会超,我的想法是用数组模拟链表,left[i]和right[i]数组分别存放i的左值和右值。在整个过程中,逆序操作最耗时间。因为题目仅仅须要求奇数项的和,在进行逆序操作时。我们不是必需真真进行操作。仅仅须要记录逆序的次数就可以,若是奇数次,则最后求整个序列的偶数项之和。偶数次就是求奇数项之和。另一点就是,操作四的进行与否会对前两种操作有一点影响。须要稍作处理。具体过程见代码:


    //#include <algorithm>
    //#include <iostream>       //这里不能用iostream,和right,left冲突,
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long LL;
    const int maxn= 100000 + 10;
    
    int left[maxn],right[maxn];
    void link(int L, int R) {       //连接L和R。L在左边
        right[L] = R;
        left[R] = L;
    }
    int main() {
        int n,m,cas=1;
        while(~scanf("%d%d",&n,&m)) {
            for(int i=0; i<=n; i++) {
                link(i,i+1);
            }
            left[0]=n;
            right[n]=0;
            int op,flag=0,x,y;
            while(m--) {
                scanf("%d",&op);
                if(op==4) {         //推断是否进行逆序操作
                    flag=!flag;
                    continue;           //注意:当op==4时。不须要输入x,y.(这里找错找了好久……%>_<%……)
                }
                scanf("%d%d",&x,&y);
                if(op==3 && right[y]==x)    swap(x,y);  //方便后面推断交换是否相邻
                if(op!=3 && flag) op=3-op;          //进行逆序操作后。原来的左边变成右边。右边变成左边
                if(op==1 && left[y]==x) continue;
                if(op==2 && right[y]==x) continue;
                int lx=left[x],rx=right[x],ly=left[y],ry=right[y];
                if(op==1) {                 //将x移到y的左边
                    link(lx,rx);
                    link(ly,x);
                    link(x,y);
                } else if(op==2) {          //将x移到y的右边
                    link(lx,rx);
                    link(y,x);
                    link(x,ry);
                } else if(op==3) {          //交换x和y
                    if(right[x]==y) {       //当x和y相邻时
                        link(lx,y);
                        link(y,x);
                        link(x,ry);
                    } else {                //当x和y不相邻时
                        link(lx,y);
                        link(y,rx);
                        link(ly,x);
                        link(x,ry);
                    }
                }
            }
            LL sum=0;
            int b=0;
            for(int i=1; i<=n; i++) {
                b=right[b];
                if(i%2) sum+=b;
            }
            if(flag && n%2==0) sum=(LL)n*(n+1)/2-sum;
            //假设逆序操作次数为奇数,则终于结果求的是整个序列的偶数项之和,此处是用 序列总和减去奇数项之和
            printf("Case %d: %lld
    ",cas++,sum);
            //此处输出太坑了,因为cb仅仅支持__int64,不支持%lld。而hustoj支持longlong不支持int64,WA了几次
        }
        return 0;
    }


    測试数据:

    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


    输出答案:
    Case 1: 12  
    Case 2: 9  
    Case 3: 2500050000
    



    可惜这题在比赛时思路是对的。因为各种问题考虑不全没有做出来……还好仅仅是普通的练习赛。

    。。


  • 相关阅读:
    洛谷 1443——马的遍历(广度优先搜索)
    jzoj C组 2017.1.21
    jzoj C组 2017.1.20 比赛
    jzoj C组 2017.1.19 比赛
    jzoj C组 2017.1.18 比赛
    jzoj C组 2017.1.17 比赛
    jzoj C组 2017.1.16 比赛
    jzoj C组 2017.1.15比赛
    [LCA][数学]JZOJ 4794 富爷说是一棵树
    [CDQ分治][带权并查集]JZOJ 4769
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7052559.html
Copyright © 2011-2022 走看看