UVA 12657

双向链表

///双向链表---节点
///如果数据结构上的某一个操作很耗时,有时可以用加标记的方式处理,而不需要真的去执行那个操作,
///但同时,该数据结构的所有其他操作都要考虑这个操作
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdlib>

using namespace std;
#define maxn 100005
int Right[100005],Left[100005];

void link(int L, int R)///辅助函数是两个节点相互连接
{
    Right[L]=R;
    Left[R]=L;
}

int main()
{
    int n,m;
    int op;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)
        {
            Left[i]=i-1;
            Right[i]=(i+1)%(n+1);
        }
        Right[0]=1;
        Left[0]=n;

        int inv=0;
        int X,Y;
        while(m--)
        {
            cin>>op;
            if(op==4)
                inv=1;
            else
            {
                cin>>X>>Y;
                if(op==3&&Right[Y]==X)  swap(X,Y);///交换后使得Y保证在X的右边,利于后面的统一交换操作
                if(op!=3&&inv)  op=3-op;
                if(op==1&&Right[X]==Y)  continue;
                if(op==2&&Right[Y]==X)  continue;

                int LX=Left[X], RX=Right[X], LY=Left[Y], RY=Right[Y];///这一步至关重要,倘若不使用这一步,在连接节点的过程中,原始值会发生改变,会导致之后系列的连接出错
                if(op==1)
                {
                    link(LX,RX);
                    link(X,Y);
                    link(LY,X);
                }
                else if(op==2)
                {
                    link(LX,RX);
                    link(Y,X);
                    link(X,RY);
                }
                else if(op==3)
                {
                    if(RX==Y)
                    {
                        link(LX,Y);
                        link(Y,X);
                        link(X,RY);
                    }
                    else
                    {
                        link(LX,Y);
                        link(Y,RX);
                        link(LY,X);
                        link(X,RY);
                    }
                }
            }
        }
        int t=0;
        long long ans=0;///防止数据溢出
        for(int i=1; i<=n; i++)
        {
            t=Right[t];
            if(i%2)
                ans+=t;
        }
        if(inv&&n%2==0) ans=(long long)n*(n+1)/2-ans;
                cout<<ans<<endl;
    }

    return 0;
}

时间: 2024-10-17 08:30:49

UVA 12657的相关文章

uva 12657 - Boxes in a Line(AC和TLE的区别,为什么说STL慢..)

用STL中的list写的,TLE #include<cstdio> #include<iostream> #include<cstring> #include<list> #include<algorithm> using namespace std; list<int> l; list<int>::iterator it1,it2,it3,it4,it5,it; void work(int a,int a1=1,int

UVa 12657 Boxes in a Line(双向链表的应用)

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 th

Uva 12657 双向链表

题目链接:https://uva.onlinejudge.org/external/126/12657.pdf 题意: 给你一个从1~n的数,然后给你操作方案 • 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

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. 操作四:将

Uva 12657 Boxes in a Line 双向链表

操作4比较特殊,为了避免一次性修改所有元素的指针,由于题目只要求输出奇数盒子的编号,所以我们可以灵活的根据是否进行过操作4对操作1 操作2 进行改动 操作3不受操作4影响 上代码.... #include<cstdio> #include<algorithm> const int maxn=100000+5; int right[maxn],left[maxn]; void link (int L,int R){ right[L]=R;left[R]=L; } //在双向链表这样复

双向链表 Boxes in a Line UVA - 12657

首先记录一下对链表的理解,最初看链表是在教材上看的,上面是用结构体, 理解起来还不是很困难,我也以为自己懂了,然而看到紫书上链表用的是数组(UVA11988),真的是..到最后把他的代码背下来了都还是有点晕(/(ㄒoㄒ)/~~),那个时候做题有点匆忙,也就没深究,不过后面那道(也就是这道)也就没再写了,差不多隔了一个月吧,有那么一点点感觉就是这次没看代码自己写过一遍后. 单向每一个结构体有两个元素(或者更多),其中一个是下一个元素的地址,其他的是他本身有的东西,在这道题中,1 2 3 4 5,

UVa 12657 Boxes in a Line(应用双链表)

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 th

UVA 12657 Boxes in a Line(双向链表+小技巧)

题意:对于一行按照顺序排列盒子数字与位置都为 1,2,3,4....n 执行四种操作 c = 1    x 放到 y 的左边 c =2     x 放到 y 的右边 c =3 交换 x, y c =4 颠倒链 最后求出奇数位置的数的总和 题解:直接维护无论如何每次每次都需要维护一段区间的位置,因此不去看位置.只需要知道每个盒子左边是哪个盒子右边是哪个盒子 这样就直接使用双向链表维护,接着颠倒时注意只是标记就好 最后注意几个细节: 首先颠倒后1与2的交换需要互换: 维护链表时可以提取出一个函数,每

uva 12657(双向链表)

一定要注意swap(x, y),x, y可能相邻! #include <cstdio> #define N 100005 #define ll long long int n, m; struct node{ int l, r; node() : l(0), r(0) {} node(int l_, int r_) : l(l_), r(r_) {} }num[N]; void init() { for(int i = 0; i <= n + 1; i++) num[i].l = i -

Uva 12657 移动盒子(双向链表)

题意: 你有一行盒子,从左到右依次编号为1, 2, 3,-, n.可以执行以下4种指令:1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令).2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令).3 X Y表示交换盒子X和Y的位置.4 表示反转整条链. 分析: 从操作1,2来看, 需要有一个数据结构, 记录每个盒子左边和右边是什么. 操作4如果真的模拟复杂度较高也比较麻烦, 可以考虑建一个标记, 表示有没执行过操作4 但是注意了 如果执行了操作4后,