zoukankan      html  css  js  c++  java
  • 【离线做法】可持久化的书橱

    相信那些数据结构题做多的大佬,在看完题之后立马用主席树切了此题

    题目描述

    Verland 是一个神奇的星球,蒟蒻妹子进入宫殿之后发现了一个 N 层,每层有 M 个格子的神奇书橱,她可以对这个书橱做如下操作:

    • 1 i j:在第 i 层的第 j 格放入一本书(如果之前有则这次操作无效)
    • 2 i j :将放在第 i 层的第 j 格的书取走(如果之前没有则这次操作无效)
    • 3 i:将第 i 层的格子翻转,有书的格子变成没有,没有的变成有
    • 4 i:返回第 i 次操作后书橱的状态

    蒟蒻妹子想知道每次操作后书橱上的书的总数。

    由于蒟蒻妹子觉得数数很累,于是她想让你帮助她解决这个问题.

    输入格式

    第 1 行三个整数 N,M,Q

    接下来 Q 行 第一个数表示操作类型,接下来的输入如题意所说

    输出格式

    总共 Q 行,每行一个整数,表示这次询问的答案

    数据规模与约定

    保证数据合法

    Subtask 1 (27):N1000,M1000,Q100000,操作 4 的次数4

    Subtask 2 (25):N100,M100,Q100

    Subtask 3 (13):N=1000,M=1000,Q=300000

    Subtask 4 (13):N=1000,M=1000,Q=300000

    Subtask 5 (13):N=1000,M=1000,Q=300000

    时间限制:1s

    空间限制:512MB


    题目分析

    做法一:强行模拟可持久化

    记录每一个要被返回到的状态,返回时直接赋值上即可。

    处理细节例如操作怎么处理没有什么好说的。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_HISTORY = 4103;
     4 int n,m,q,ans[300035],k[1003],tot;
     5 int lb[300035];
     6 struct node
     7 {
     8     int tt,x,y;
     9 }s[300035];
    10 bitset<1003> f[1003];
    11 bitset<1003> sv[MAX_HISTORY][1003];
    12 int his[MAX_HISTORY][1003];
    13 int read()
    14 {
    15     char ch = getchar();int num = 0;
    16     for (; !isdigit(ch); ch = getchar());
    17     for (; isdigit(ch); ch = getchar())
    18         num = (num<<1)+(num<<3)+ch-48;
    19     return num;
    20 }
    21 int main()
    22 {
    23     n = read();m = read();q = read();
    24     for (int i=1; i<=q; i++)
    25     {
    26         s[i].tt = read();s[i].x = read();
    27         if (s[i].tt <= 2)s[i].y = read();
    28         if (s[i].tt==4)if (!lb[s[i].x])lb[s[i].x] = ++tot;
    29     }
    30     register int i,j;
    31     for (i=1; i<=q; i++)
    32     {
    33         int ansk = ans[i-1],tt = s[i].tt,x = s[i].x,y = s[i].y;
    34         if (tt==1){
    35             if (!f[x][y]){
    36                 f[x][y] = 1;
    37                 k[x]++;ansk++;
    38             }
    39         }else if (tt==2){
    40             if (f[x][y]){
    41                 f[x][y] = 0;
    42                 k[x]--;ansk--;
    43             }
    44         }else if (tt==3){
    45             f[x].flip();
    46             ansk += m-2*k[x];
    47             k[x] = m-k[x];
    48         }else if (tt==4){
    49             ansk = ans[x];
    50             for (int j=1; j<=n; j++)
    51                 f[j] = sv[lb[x]][j],k[j]=his[lb[x]][j];
    52         }
    53         if (lb[i]){for (j=1; j<=n; j++)sv[lb[i]][j] = f[j],his[lb[i]][j]=k[j];}
    54         printf("%d
    ",ansk);
    55         ans[i] = ansk;
    56     }
    57     return 0;
    58 } 

    加上bitset乱搞可过52分。

    做法二:典型离线题

    不一定非得拘泥于「可持久化」的题目名字。

    站在另一种角度想一想:把每一个状态看做是一个节点,节点与节点之间的转移就是不同的操作。这样一来,根本无需存储需要返回的状态,而是在这样一张新的图上dfs回溯就可以了。

    那么这就是一道典型的离线题。

    举个例子,假设现在没有4号操作,那么整张图操作顺序可以看成这样:

    再而,按照每一个节点操作下去就可以了。

    又如果有了4号操作,操作顺序可以表示成这样:

     

    其中5号节点的操作是返回2号节点;7号节点操作是返回5号节点。

    值得注意的是,有可能返回0号节点(初始状态)

    那么只要dfs从0开始就可以了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<bitset>
     6 
     7 struct node
     8 {
     9     int tt,x,y;
    10 }a[300035];
    11 struct scenario
    12 {
    13     std::bitset<1003> f[1003];
    14     bool fpd;
    15     int k[1003];
    16 }f;
    17 int n,m,q,ans[300035];
    18 std::vector<int> otd[300035];
    19 
    20 void dfs(int now)
    21 {
    22     if (now > q) return;
    23     int i = a[now].x, j = a[now].y, delta = 0;
    24     if (a[now].tt==1)
    25         if (!f.f[i][j]){
    26             delta++;
    27             f.k[i]++;
    28             f.f[i][j] = 1;
    29         }
    30     if (a[now].tt==2)
    31         if (f.f[i][j]){
    32             delta--;
    33             f.k[i]--;
    34             f.f[i][j] = 0;
    35         }
    36     if (a[now].tt==3)
    37     {
    38         delta = m-2*f.k[i];
    39         f.k[i] = m-f.k[i];
    40         f.f[i].flip();
    41     }
    42     ans[now] += delta;
    43     for (unsigned int i=0; i<otd[now].size(); i++)
    44     {
    45         ans[otd[now][i]] = ans[now];
    46         dfs(otd[now][i]);
    47     }
    48     i = a[now].x, j = a[now].y;
    49     if (a[now].tt==1 && delta==1)
    50     {
    51         f.k[i]--;
    52         f.f[i][j] = 0;
    53     }
    54     if (a[now].tt==2 && delta==-1)
    55     {
    56         f.k[i]++;
    57         f.f[i][j] = 1;
    58     }
    59     if (a[now].tt==3)
    60     {
    61         f.k[i] = m-f.k[i];
    62         f.f[i].flip();
    63     }
    64 }
    65 int read()
    66 {
    67     char ch = getchar();int num = 0;
    68     for (; !isdigit(ch); ch = getchar());
    69     for (; isdigit(ch); ch = getchar())
    70         num = (num<<1)+(num<<3)+ch-48;
    71     return num;
    72 }
    73 int main()
    74 {
    75     n = read();
    76     m = read();
    77     q = read();
    78     otd[0].push_back(1);
    79     for (int i=1; i<=q; i++)
    80     {
    81         if ((a[i].tt = read()) <= 2)
    82             a[i].x = read(),a[i].y = read();
    83         else a[i].x = read();
    84         if (a[i].tt!=4) otd[i-1].push_back(i);
    85         else otd[a[i].x].push_back(i);
    86     }
    87     dfs(0);
    88     for (int i=1; i<=q; i++)
    89         printf("%d
    ",ans[i]);
    90     return 0;
    91 }

     做法三:主席树

    END

  • 相关阅读:
    截取nginx日志
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    gitlab给用户添加提交到主干的权限
    动手为王 | Oracle 数据库跨版本升级迁移实践
    ie8关于@font-face无效的兼容问题
    web自定义中文字体
    django 前后台交互过程
  • 原文地址:https://www.cnblogs.com/antiquality/p/8861569.html
Copyright © 2011-2022 走看看