zoukankan      html  css  js  c++  java
  • 色板游戏

    题目链接

    题目描述

    给定一个 (n) 项的数列,初始颜色都为 (1),有 (m) 次操作,(T) 种颜色,分为 (2) 种:

    (space space space space space space) 把区间 ([a, space b]) 改为一个颜色 (c)

    $space space space space space space $ 询问区间 ([a, space b]) 有多少不同的颜色

    数据范围

    (1 leq n leq 10^5, space 1 leq T leq 30, space 1 leq m leq 10^5)

    Solution

    想到最暴力的做法:对于每种颜色维护一棵线段树,就有 (3) 种操作:区间推平、区间清空和区间求和(其实也可以不写求和)

    考虑标记 (2)(mathrm{tag}) 来分别维护区间推平和区间清空,在下压的时候还应该考虑两个 (mathrm{tag}) 获得的先后顺序。因此我们需要记录每个 (mathrm{tag}) 获得的时间戳,用来判断到底该下压哪个 (mathrm{tag})

    (mathrm{push space down}) 操作时一定要注意,两个 (mathrm{tag}) 一起清空,两个儿子的时间戳和要下放的时间戳 (mathrm{max}).

    总复杂度 (mathrm{O(Tm log_n)})

    Code

    因为博主太菜了,感觉本题及其卡时间和空间。吸氧 (+ space C^{++}11) 才能跑过。

    ([) 题外话 (]) 极其悲惨的评测记录(这还只是一部分

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define re register
    using namespace std;
    
    const int N = 100010;
    int n, T, O, sum[31][N << 2], tag[31][N << 2], clear[31][N << 2];
    
    void push_up(int x, int k) { sum[k][x] = sum[k][x << 1] + sum[k][x << 1 | 1]; }
    void push_down(int x, int l, int r, int k) 
    {
        int mid = (l + r) >> 1, t = tag[k][x], c = clear[k][x];
        if(!t && !c) return ;
        if(t < c)
        {
            clear[k][x << 1] = max(clear[k][x << 1], c);
            clear[k][x << 1 | 1] = max(clear[k][x << 1 | 1], c);
            sum[k][x << 1] = sum[k][x << 1 | 1] = 0;
        }
        else
        {
            tag[k][x << 1] = max(tag[k][x << 1], t);
            tag[k][x << 1 | 1] = max(tag[k][x << 1 | 1], t); 
            sum[k][x << 1] = mid - l + 1;
            sum[k][x << 1 | 1] = r - mid;
        }
        clear[k][x] = tag[k][x] = 0;
        return ;
    }
    void add(int x, int l, int r, int stdl, int stdr, int k, int tim)
    {
        if(stdl <= l && stdr >= r)
        {
            tag[k][x] = tim, sum[k][x] = r - l + 1;
            push_down(x, l, r, k);
            return ;
        }
        int mid = (l + r) >> 1;
        push_down(x, l, r, k);
        if(stdl <= mid) add(x << 1, l, mid, stdl, stdr, k, tim);
        if(stdr > mid) add(x << 1 | 1, mid + 1, r, stdl, stdr, k, tim);
        push_down(x, l, r, k), push_up(x, k);
    } 
    void del(int x, int l, int r, int stdl, int stdr, int k, int tim)
    {
        if(stdl <= l && stdr >= r)
        {
            clear[k][x] = tim, sum[k][x] = 0;
            push_down(x, l, r, k);
            return ;
        }
        int mid = (l + r) >> 1;
        push_down(x, l, r, k);
        if(stdl <= mid) del(x << 1, l, mid, stdl, stdr, k, tim);
        if(stdr > mid) del(x << 1 | 1, mid + 1, r, stdl, stdr, k, tim);
        push_down(x, l, r, k), push_up(x, k);
    }
    int query(int x, int l, int r, int stdl, int stdr, int k)
    { 
        if(l > stdr || r < stdl) return 0;
        if(stdl <= l && stdr >= r) return sum[k][x];
        int mid = (l + r) >> 1;
        push_down(x, l, r, k);
        return query(x << 1, l, mid, stdl, stdr, k) + 
        query(x << 1 | 1, mid + 1, r, stdl, stdr, k);
        push_down(x, l, r, k), push_up(x, k);
    }
    
    char opt;
    int a, b, c, cnt = 1;
    
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return x;
    }
    
    int main()
    {
        n = read(), T = read(), O = read();
        tag[1][1] = 1, sum[1][1] = n;
        while(O--)
        {
            cin >> opt;
            if(opt == 'C')
            {
                a = read(), b = read(), c = read();
                if(a > b) swap(a, b);
                for(re int i = 1; i <= T; i++)
                    cnt++, del(1, 1, n, a, b, i, cnt);
                cnt++, add(1, 1, n, a, b, c, cnt);
            }
            else
            {
                a = read(); b = read();
                if(a > b) swap(a, b);
                int res = 0;
                for(re int i = 1; i <= T; i++)
                    if(query(1, 1, n, a, b, i) > 0) res++;
                printf("%d
    ", res);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    GCC-windows的预编译版本——nuwen MinGW
    stm32 flash和sram
    NAND Flash和NOR Flash的比较
    emwin如何在windows10下vs2015或2017进行仿真。
    IIC简介(转载)
    ubuntu版本查看
    下载速度更加快的 SourceForge 镜像
    使用virtualbox安装的Ubuntu,窗口分辨率过小,使用增强工具完成和vmtools一样的功能。
    C#中的结构体与类的区别
    理解C#值类型和引用类型
  • 原文地址:https://www.cnblogs.com/Andy-park/p/14067004.html
Copyright © 2011-2022 走看看