• cf707D. Persistent Bookcase(离线+dfs)


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

     有一个n*m的书架,有K个操作,求每个操作后一共有多少本书;有4种操作;

    1:x y 如果 x y 位置没有书,放一本书在上面;

    2:x y如果 x y 位置有书,移走;

    3:x,表示把第x行的所有又书的拿走,没书的放上去;

    4:k,回到第k个操作后的状态;

    离线处理k个操作;当操作不为 4 时,把操作i连在i-1后,=4时把操作 i 连在a[i].x后;

    这样建一棵树,然后遍历即可,在回溯的时候注意更改书架的状态即可;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    #include<vector>
    using namespace std;
    #define N 1005
    #define PI 4*atan(1.0)
    #define mod 1000000007
    #define met(a, b) memset(a, b, sizeof(a))
    typedef long long LL;
    
    struct node
    {
        int op, x, y, ans;
    }a[N*N];///k个操作;
    
    int cnt[N][N];///记录书架的状态;
    int n, m, k;
    vector<vector<int> > G;///操作形成的图;
    
    void dfs(int u)
    {
        if(a[u].op == 1)
        {
            int flag = 0;
            if(cnt[a[u].x][a[u].y] == 0)
            {
                flag = 1;
                a[u].ans ++;///在已有的基础上加上更改的值;
                cnt[a[u].x][a[u].y] = 1;///标记状态;
            }
            for(int i=0, len=G[u].size(); i<len; i++)
            {
                int v = G[u][i];
                a[v].ans = a[u].ans;///往下走的时候,v是u的儿子,所以拥有u的ans;
                dfs(v);
            }
            if(flag)///回溯时要重新更改状态;
                cnt[a[u].x][a[u].y] = 0;
        }
        else if(a[u].op == 2)
        {
            int flag = 0;
            if(cnt[a[u].x][a[u].y] == 1)
            {
                flag = 1;
                a[u].ans --;
                cnt[a[u].x][a[u].y] = 0;
            }
            for(int i=0, len=G[u].size(); i<len; i++)
            {
                int v = G[u][i];
                a[v].ans = a[u].ans;
                dfs(v);
            }
            if(flag)
                cnt[a[u].x][a[u].y] = 1;
        }
        else if(a[u].op == 3)
        {
            int num = 0;
            for(int i=1; i<=m; i++)
            {
                if(cnt[a[u].x][i] == 1)
                    num ++;
                cnt[a[u].x][i] ^= 1;
            }
            a[u].ans = a[u].ans - num + (m-num);///更新ans;
            for(int i=0, len=G[u].size(); i<len; i++)
            {
                int v = G[u][i];
                a[v].ans = a[u].ans;
                dfs(v);
            }
            for(int i=1; i<=m; i++)
                cnt[a[u].x][i] ^= 1;
        }
        else
        {
            for(int i=0, len=G[u].size(); i<len; i++)
            {
                int v = G[u][i];
                a[v].ans = a[u].ans;
                dfs(v);
            }
        }
    }
    
    int main()
    {
        while(scanf("%d %d %d", &n, &m, &k)!=EOF)
        {
            met(a, 0);
            met(cnt, 0);
            G.clear();
            G.resize(k+5);
    
            for(int i=1; i<=k; i++)
            {
                scanf("%d", &a[i].op);
                if(a[i].op <= 2)
                    scanf("%d %d", &a[i].x, &a[i].y);
                else
                    scanf("%d", &a[i].x);
    
                if(a[i].op <= 3)
                    G[i-1].push_back(i);
                else
                    G[a[i].x].push_back(i);
            }
    
            for(int i=0, len=G[0].size(); i<len; i++)
                dfs(G[0][i]);
    
            for(int i=1; i<=k; i++)
                printf("%d
    ", a[i].ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    yii 面包屑
    php == ===
    算法竞赛入门经典 暴力求解法 简单枚举 7.1.4 双基回文数
    算法竞赛入门经典 暴力求解法 简单枚举 7.1.4 双基回文数
    算法竞赛入门经典 暴力求解法 简单枚举 7.1.4 双基回文数
    算法竞赛入门经典 暴力求解法 简单枚举 7.1.4 双基回文数
    折半(对半)搜索算法
    折半(对半)搜索算法
    折半(对半)搜索算法
    折半(对半)搜索算法
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5793466.html
Copyright © 2020-2023  润新知