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的交换需要互换;

    维护链表时可以提取出一个函数,每次都只需要多次使用这个函数;

    c等于1,2,3时x与y的位置相邻时会出现很大的问题

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1LL<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=100010;
struct node
{
    int left,right;
} ball[Max];//**表示i这个数字左右两边的数字**
void initPosition(int n)//双向链表初始化
{
    for(int i=1; i<=n; ++i)
    {
        ball[i].left=i-1;
        ball[i].right=(i+1)%(n+1);
    }
}
void link(int l,int r)//左右相互连接
{
    ball[l].right=r;
    ball[r].left=l;
}
inline void Solve(int type,int &mark)
{
    if(type==4)
    {
        mark=(mark^1);
        return;
    }
    if(type!=3&&!mark)
        type=3-type;//注意反转后只需交换type的1与2就好
    int x,y;
    scanf("%d %d",&x,&y);
    int Lx=ball[x].left;
    int Rx=ball[x].right;
    int Ly=ball[y].left;
    int Ry=ball[y].right;
    if(type==1&&Rx==y||type==2&&Lx==y)
        return;
    if(type==1)//通过下标找到x、y,将x放在y的左边
    {
        link(Lx,Rx);//**找到6个交换的规律**
        link(Ly,x);
        link(x,y);
    }
    else if(type==2)
    {
        link(Lx,Rx);
        link(x,Ry);
        link(y,x);
    }
    else if(type==3)
    {
        if(Rx==y)//注意
        {
            link(Lx,y);
            link(y,x);
            link(x,Ry);
        }
        else if(Lx==y){
            link(y,Rx);
            link(Ly,x);
            link(x,y);
        }
        else
        {
            link(y,Rx);
            link(Ly,x);
            link(Lx,y);
            link(x,Ry);
        }
    }
}
ll Print(int n,int mark)
{
    ll res=0LL;
    int start=0;
    for(int i=1; i<=n; ++i)
    {
        if(ball[i].left==0)
        {
            start=i;
            break;
        }
    }
    int now=start;
    int coun=0;
    while(now)
    {
        res+=now;
        now=ball[now].right;
        if(now)
            now=ball[now].right;
    }
    if(!(n&1)&&!mark)
        res=(ll)n*(n+1)/2-res;
    return res;
}
int main()
{
    int n,m;
    int coun=0;
    while(~scanf("%d %d",&n,&m))
    {
        initPosition(n);
        int mark=1;//标记是否反转
        while(m--)
        {
            int type;
            scanf("%d",&type);
            Solve(type,mark);
        }
        printf("Case %d: %lld\n",++coun,Print(n,mark));
    }
    return 0;
}
时间: 2024-08-06 03:44:34

UVA 12657 Boxes in a Line(双向链表+小技巧)的相关文章

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 双向链表

操作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; } //在双向链表这样复

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 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(数组模拟双链表)

题目链接 1 /* 2 问题 3 将一排盒子经过一系列的操作后,计算并输出奇数位置上的盒子标号之和 4 5 解题思路 6 由于数据范围很大,直接数组模拟会超时,所以采用数组模拟的链表,left[i]和right[i]分别表示i号盒子的左边是谁和右边 7 是谁.特别提醒,4这个操作可以采用其他的办法去标记,而不必真的去模拟交换,否则会超时. 8 */ 9 10 #include<cstdio> 11 #include<algorithm> 12 13 using namespace

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 the right to

Uva12657 (Boxes in a Line)移动盒子

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 4kinds 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

UVA12657 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 (ig