例题6-5 UVA12657 Boxes in a Line(33行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题6-5 UVA12657 Boxes in a Line(33行AC代码)

题目大意

对升序排列的n个数字(1开始编号)进行一系列操作,输出最终序列的奇位数之和。操作如下:

  • 1 X Y:把X移到Y左侧
  • 2 X Y:把X移到Y右侧
  • 3 X Y:交换X和Y
  • 4:反转序列(逆置)

思路分析

若是直接用链表模拟,在查找和反转时会消耗大量时间,导致超时,因此,如何解决这两个问题是关键。

  • 查找:为了简化,可用STL的list模拟链表,同时定义pos存储每个数对应的链表指针,在查询时时间复杂度为O(1)
vector<list<int>::iterator> pos(n+1);
  • 反转:不一定真正去反转链表,可定义开关标记inv=0,其中inv=1表示反转一次,再次反转则inv=0,由于增加了标记,那么每个操作均需考虑标记的值,当inv=1时,考虑如下情况:
    • 当op=1或2时,则需做相反操作,即op=3-op
    • 当op=3时,交换不受影响
    • 当op=4时,inv=0
    • 当输出时,若链表个数为偶数,则输出下标为偶数的元素和;否则均输出奇数下标的元素之和

注意点

  • 最后计算总和时需用long long保存,否则会溢出

AC代码(C++11,链表,反转标记优化)

#include<bits/stdc++.h>
using namespace std;
int n, m, op, a, b, num=0;
int main() {
    while (scanf("%d %d", &n, &m) == 2) {
        list<int> l(n); // 存储1-n
        vector<list<int>::iterator> pos(n+1); // pos[i]表示数字i在list中的指针
        int idx=1, inv=0;
        for (auto p=l.begin(); p != l.end(); p++, idx++) { // 初始化
            *p = idx;
            pos[idx] = p;
        }
        for (int i = 0; i < m; i ++) { // m个操作
            scanf("%d", &op);
            if (op != 4) scanf("%d %d", &a, &b);
            if (op == 4) inv = !inv; // 反转标记
            else if (op == 3) swap(*pos[a],*pos[b]), swap(pos[a], pos[b]); // 交换
            else {
                l.erase(pos[a]); // 先擦除
                if (inv == 1) op = 3 - op; // 反转则左右交换
                auto p=pos[b];
                if (op == 2) p ++; // 插入右侧
                pos[a] = l.insert(p, a); // a的新位置
            }
        }
        long long cnt=1, oddsum=0; // 避免溢出
        for (auto p=l.begin(); p != l.end(); p++, cnt++) {
            if (cnt % 2 == 1) oddsum += *p;
        }
        printf("Case %d: %lld\n", ++num, (inv == 1 && n%2 == 0) ?  (long long)n*(n+1)/2-oddsum : (long long)oddsum);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值