zoukankan      html  css  js  c++  java
  • Uva12657 Boxes in a Line

    题目链接:传送门

    分析:每次操作都会花费大量时间,显然我们只需要关注每个元素的左边是啥,右边是啥就够了,那么用双向链表,l[i]表示i左边的数,r[i]表示i右边的数,每次操作模拟一下数组的变化就好了.

          不过这样有一个问题:第4个操作似乎无法很高效地进行,如果真的按照它说的那样模拟翻转,恐怕复杂度和暴力也要差不多了,那么我们怎么处理呢?

          观察发现题目只让我们输出奇数位置的编号和,也就是说,如果题目给定的序列长度就是奇数的,那么无论用多少次4操作都没有影响,否则4的次数是奇数,则用总和减去当前奇数位置的和就是答案。这就相当于线段树中的lazy标记的做法,现在要考虑这个标记对其它操作的影响,显然对3操作是没有任何影响的,而对1,2操作无非就是把1变成了2,把2变成了1,这样就很快地就能解决问题了。

    如果数据结构上的某一个操作很耗时,有时可以用加标记的方式处理,而不需要真的执行那个操作。但同时,该数据结构的所有其他操作都要考虑这个标记!

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 100010;
    
    int n, m, kase, l[maxn], r[maxn],flag;
    long long ans;
    
    int main()
    {
        while (scanf("%d%d", &n, &m) == 2)
        {
            for (int i = 1; i <= n; i++)
            {
                l[i] = i - 1;
                r[i] = (i + 1) % (n + 1);
            }
            l[0] = n; 
            r[0] = 1;
            flag = 0;
            for (int i = 1; i <= m; i++)
            {
                int op,x,y;
                scanf("%d", &op);
                if (op == 4)
                    flag = (flag + 1) % 2;
                else
                {
                    scanf("%d%d", &x, &y);
                    if (op != 3 && flag)
                        op = 3 - op;
                    if (op == 1 && l[y] == x)
                        continue;
                    if (op == 2 && r[y] == x)
                        continue;
                    
                    if (op == 1)
                    {
                        l[r[x]] = l[x];
                        r[l[x]] = r[x];
                        r[l[y]] = x;
                        r[x] = y;
                        l[x] = l[y];
                        l[y] = x;
                    }
                    else
                        if (op == 2)
                        {
                        l[r[x]] = l[x];
                        r[l[x]] = r[x];
                        l[x] = y;
                        r[x] = r[y];
                        l[r[y]] = x;
                        r[y] = x;
                        }
                        else
                            if (op == 3)
                            {
                        if (r[x] == y)
                        {
                            r[l[x]] = y;
                            l[y] = l[x];
                            r[y] = x;
                            l[x] = y;
                            r[x] = r[y];
                            l[r[y]] = x;
                        }
                        else
                        {
                            r[l[y]] = x;
                            l[r[y]] = x;
                            r[l[x]] = y;
                            l[r[x]] = y;
                            swap(l[x], l[y]);
                            swap(r[x], r[y]);
                        }
                            }
                }
                int cur = 0;
                ans = 0;
                for (int i = 1; i <= n; i++)
                {
                    cur = r[cur];
                    if (i % 2 == 1)
                        ans += cur;
                }
                if (flag && n % 2 == 0)
                    ans = (long long)n * (n + 1) / 2 - ans;
            }
            printf("Case %d: %lld
    ", ++kase, ans);
        }
    
        return 0;
    }
  • 相关阅读:
    [ 字典树题目 ]
    AC Challenge [ ACM-ICPC 2018 南京赛区网络预赛 ] [dfs + 二进制记忆化搜索 ]
    ACM-ICPC 2018 南京赛区网络预赛 J.Sum [ 类打表 ]
    Bzoj 3224.普通平衡树 [ 权值线段树 ]
    IP:网际协议
    网络概述
    HashSet
    idea中git各颜色文件含义
    keytool证书管理
    openssl证书管理
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7571319.html
Copyright © 2011-2022 走看看