zoukankan      html  css  js  c++  java
  • Codeforces 707D Persistent Bookcase(时间树)

    【题目链接】 http://codeforces.com/problemset/problem/707/D

     

    【题目大意】

      给出一个矩阵,要求满足如下操作,单个位置x|=1或者x&=0,一行的数全部取反,回到第k个操作。要求每次操作后输出这个矩阵中数字的和。

    【题解】

      由于存在操作回溯,考虑使用可持久化数据结构或者建立离线操作树。因为懒,没写持久化。对于每个操作,将它和时间顺序上的上一个节点连边,这样子就形成了一棵树,对这棵树从根节点开始遍历,递归处理,每次处理完一棵子树就回溯操作,这样子就能离线处理操作的持久化了。

    【代码】

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N=1005,M=100005;
    int k,q,n,m,t[N],f[N][N],s[N],last=0,ans[M],op[M],x[M],y[M],id[M];
    vector<int> v[M];
    void dfs(int pre,int w){
        int flag=0;
        if(op[w]==1){
            if(f[x[w]][y[w]]^t[x[w]])ans[w]=ans[pre];
            else{
                f[x[w]][y[w]]^=1;
                if(f[x[w]][y[w]])s[x[w]]++,flag=1;else s[x[w]]--;
                ans[w]=ans[pre]+1;
            }
        }else if(op[w]==2){
            if(f[x[w]][y[w]]^t[x[w]]){
                f[x[w]][y[w]]^=1;
                if(f[x[w]][y[w]])s[x[w]]++,flag=1;else s[x[w]]--;
                ans[w]=ans[pre]-1;
            }else ans[w]=ans[pre];
        }else if(op[w]==3){
            if(t[x[w]]==0)ans[w]=ans[pre]-s[x[w]]+m-s[x[w]];
            else ans[w]=ans[pre]-(m-s[x[w]])+s[x[w]];
            t[x[w]]^=1;
        }
        for(int i=0;i<v[w].size();i++)dfs(w,v[w][i]);
        if(op[w]==1){
            if(ans[w]!=ans[pre]){
                f[x[w]][y[w]]^=1;
                if(flag)s[x[w]]--;else s[x[w]]++;
            }
        }else if(op[w]==2){
            if(ans[w]!=ans[pre]){
                f[x[w]][y[w]]^=1;
                if(flag)s[x[w]]--;else s[x[w]]++;
            }
        }else if(op[w]==3){
            t[x[w]]^=1;
        }
    }
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=q;i++){
            scanf("%d",&op[i]);
            if(op[i]==1){
                scanf("%d%d",x+i,y+i);
                v[last].push_back(id[i]=i);
                last=i;
            }else if(op[i]==2){
                scanf("%d%d",x+i,y+i);
                v[last].push_back(id[i]=i);
                last=i;
            }else if(op[i]==3){
                scanf("%d",x+i);
                v[last].push_back(id[i]=i);
                last=i;
            }else{
                scanf("%d",&k);
                last=id[i]=id[k];
            }
        }dfs(0,0);
        for(int i=1;i<=q;i++)printf("%d
    ",ans[id[i]]);
        return 0;
    }
  • 相关阅读:
    Java uuid生成随机32位
    Java 、C# Excel模板,数据一对多,主从表关系,导入到数据库
    ROS 八叉树地图构建
    操作系统基础信息搜集
    菜鸟的信息安全学习之路
    提权初探
    Windos/Linux 反弹 shell
    初读鸟哥的linux私房菜的收获
    linux中find命令的摘要
    分享一个Flink checkpoint失败的问题和解决办法
  • 原文地址:https://www.cnblogs.com/forever97/p/codeforces707d.html
Copyright © 2011-2022 走看看