UVA 12657 Boxes in a Line(双向链表)

 

这里写的并不是uva上的那个题,而是upc上的一个题,所以,稍微有些不同

 

 

 

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:
(i) 1 X Y: move box X to the left to Y (ignore this if X is already the left of Y)
(ii) 2 X Y: move box X to the right to Y (ignore this if X is already the right of Y)
(iii) 3 X Y: swap box X and Y
(iv) 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.

输入

The input contains several test cases and is terminated by End-Of-File (EOF). Each test case begins with a line containing 2 integers n, m. Each of the following m lines contain a command.
 

 

输出

For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n from left to right.

样例输入

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

样例输出

12
9
2500050000

 

题意:

给你一个n,表示长度为n的序列{1,2,3,4,5...n}

4个操作:

1,x,y,把x移动到y左边

2,x,y,把x移动到y右边

3,x,y,把x,y互换

4,翻转整个数组

题解:

模拟双向链表

记录每个数左边出现的是谁,右边出现的是谁,这样每次操作就可以O1了

对于操作4,打一个标记即可,打完标记后,1,2操作就反向了,即原本1操作要换成2操作

 

值得注意的一点是,如果要操作的两个数紧挨着(或者说相邻),那么要特殊处理,否者指针就乱了

最后结果不是t,就是wa

 

/*author:revolIA*/
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 1e6+7;
int n,m,l[maxn],r[maxn];
void debug(){
    for(int i=0;r[i]<=n;i=r[i])printf("%d ",r[i]);
    puts("");
    for(int i=n+1;l[i];i=l[i])printf("%d ",l[i]);
    puts("");
}
void connect(int x,int y){l[y] = x,r[x] = y;}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        r[0] = 1;
        l[0] = 0;
        for(int i=1;i<=n+1;i++)l[i] = i-1,r[i] = i+1;
        int flag = 0,opt,x,y;
        while(m--){
            scanf("%d",&opt);
            if(opt == 4){
                flag ^= 1;
            }else{
                scanf("%d%d",&x,&y);
                int lx = l[x],rx = r[x];
                int ly = l[y],ry = r[y];
                if(opt == 3){
                    if(l[x] == y){
                        connect(ly,x);
                        connect(x,y);
                        connect(y,rx);
                    }else if(l[y] == x){
                        connect(lx,y);
                        connect(y,x);
                        connect(x,ry);
                    }else{
                        connect(lx,y);
                        connect(y,rx);
                        connect(ly,x);
                        connect(x,ry);
                    }
                }else{
                    if(flag)opt = 3-opt;
                    if(opt == 1){
                        if(l[y] == x)continue;
                        if(l[x] == y){
                            connect(ly,x);
                            connect(x,y);
                            connect(y,rx);
                        }else{
                            connect(lx,rx);
                            connect(ly,x);
                            connect(x,y);
                        }
                    }else{
                        if(r[y] == x)continue;
                        if(r[x] == y){
                            connect(x,ry);
                            connect(y,x);
                            connect(lx,y);
                        }else{
                            connect(lx,rx);
                            connect(y,x);
                            connect(x,ry);
                        }
                    }
                }
            }
        }
        //debug();
        ll ans = 0;
        for(int i=0;r[i]<=n;i = r[r[i]])ans += r[i];
        if(n%2 == 0 && flag)ans = (1LL+n)*n/2-ans;
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值