Boxes_in_a_Line做题笔记

Boxes_in_a_Line 解题笔记

题目描述:

Background 背景

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 … n 从左到右。你的任务是模拟4种命令:

• 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y )
1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此命令)
• 2 X Y : move box X to the right to Y (ignore this if X is already the right of Y )
2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此命令)
• 3 X Y : swap box X and Y
3 X Y表示交换盒子X和Y的位置
• 4: reverse the whole line.
4表示反转整条链

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.

指令保证合法,即X不等于Y。例如,当n = 6时在初始状态下执行1 1 4后,盒子序列为2 3 1 4 5 6.接下来执行2 3 5,盒子序列变成2 1 4 5 3 6。再执行3 1 6,得到2 6 4 5 3 1。最终执行4,得到1 3 5 4 6 2。

The 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.
输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m (1 ≤ n, m ≤ 100, 000).以下m行每行包含一条指令。

The Output 输出

For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n from left to right.
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。

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

题目地址:

https://vjudge.net/problem/UVA-12657

代码:(参考紫书)

#include<iostream>
#include<algorithm>
using namespace std;

//表示链表的左指针
int left_it[100050];
//表示链表的右指针
int right_it[100050];

/**
 * was not declared in this scope:
 * 这种报错一种可能是变量未定义
 * 另一种可能是与系统的内置变量名冲突了
 * */

//将两个节点连接,让其右指针指向另一个节点的值,让另一个节点的左指针指向其值
void link(int L,int R){
    right_it[L] = R;
    left_it[R] = L;
}
/*
void oupu(){
    int b = 0;
    for(int i = 0; i <= 6; i++){
        b = right_it[b];
        cout<<b<<' ';
    }
    cout<<endl;
}*/
int main(){
    //n为编号的个数,m为操作的次数
    int n,m,k=0;
    
    while(scanf("%d%d",&n,&m) == 2){
        //赋值
        for(int i = 1; i <= n; i++){
            left_it[i] = i-1;
            right_it[i] = (i+1)%(n+1);
        }
        left_it[0] = n;
        right_it[0] = 1;
        int opera,X,Y,re = 0;
        //判断是否有反转
        while(m--){
            scanf("%d",&opera);
            if(opera == 4){
                //反转
                re = !re;
            }
            else{
                scanf("%d%d",&X,&Y);
                if(X==Y) continue;
                if(opera == 3 && right_it[Y] == X) swap(X,Y);
                if(opera == 1){
                    if(right_it[X] == Y)continue;
                    //X -> Y 的左边
                    link(left_it[X],right_it[X]);link(left_it[Y],X);link(X,Y);
                }else if(opera == 2){
                    //X -> Y 的右边
                    if(right_it[Y] == X)continue;link(left_it[X],right_it[X]);link(X,right_it[Y]);link(Y,X);
                }else if(opera == 3){
                    //X -> Y 对换
                    //交换的两个节点相连
                    if(right_it[X] == Y){
                        link(left_it[X],Y);link(Y,X);link(X,right_it[Y]);
                    }
                    //交换的两个节点不相连
                    else{
                        link(left_it[X],Y);
                        link(Y,right_it[X]);link(left_it[Y],X);link(X,right_it[Y]);
                    }
                }
            }
        }
        int b = 0;
        long long dou=0;
        //!!!!重点!!!!
        for(int i = 1; i <= n;i++){
            //计算总和
            b = right_it[b];
            if(i % 2 == 1)
            dou += b;       
        }
        if(n%2==0 && re){
            dou = (long long )n*(n+1)/2 - dou;
        }
        cout<<"Case "<<++k<<": "<<dou<<endl;
    }
    return 0;
}

分析:

  1. 思维方式很重要,因为之前很少写过关于链表的题,线性的结构基本上都是用数组比较多。所以习惯了用下标,在最后计算结果,遍历链表的时候卡壳了好久好久,最后画看了紫书上的答案,自己又画了一下草图才了解自己犯的什么错误。
  2. 还有里面有一些小的细节,真狠巧妙,就比如当操作为3的时候要判断是否有相邻,答案只给了一个种情况,我就很奇怪,后来看到上面那个swap()函数就感觉非常的巧妙!

思维错误

。所以习惯了用下标,在最后计算结果,遍历链表的时候卡壳了好久好久,最后画看了紫书上的答案,自己又画了一下草图才了解自己犯的什么错误。
2. 还有里面有一些小的细节,真狠巧妙,就比如当操作为3的时候要判断是否有相邻,答案只给了一个种情况,我就很奇怪,后来看到上面那个swap()函数就感觉非常的巧妙!

思维错误

草稿纸-6

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值