• 洛谷 P1558 色板游戏


    洛谷

    题解里面好像都是压位什么的,

    身为蒟蒻的我真的不会,

    所以就来谈谈我的30颗线段树蠢方法吧!

    这题初看没有头绪。

    然后发现颜色范围好像只有30;

    所以,我就想到一种(sao)操作,搞30颗线段树。

    每颗线段树代表一种颜色。

    那么对于题中的两种操作:

    1.修改。我们for循环扫一遍所有颜色,把其他颜色的线段树l->r修改成0,要修
    改的颜色所对应的线段树改成1。

    2.询问。也是for循环,如果(l->r)这个区间的第k种颜色所对应的线段树有值,则(ans++)

    时间复杂度也很低,大概是((MLlog(L)*T)),真正的(O()卡时()).

    献上代码:

    #include <bits/stdc++.h>
    #define ll(x) ((x)<<1)
    #define rr(x) ((x)<<1|1)
    using namespace std;
    
    const int T=31,N=100010;
    int n,t,m;
    int laz[T][N<<2],sum[T][N<<2];
    
    void pushup(int i,int x)
    {
        sum[i][x]=sum[i][ll(x)]+sum[i][rr(x)];
    }
    
    void build(int i,int x,int l,int r)
    {
        if (l==r) {
            sum[i][x]=1;
            return;
        }
        int mid=l+r>>1;
        build(i,ll(x),l,mid);
        build(i,rr(x),mid+1,r);
        pushup(i,x);
    }
    
    void pushdown(int i,int x)
    {
        if (laz[i][x]==-1) {
            sum[i][ll(x)]=sum[i][rr(x)]=0;
            laz[i][ll(x)]=laz[i][rr(x)]=-1;
        }
        else {
            sum[i][ll(x)]=sum[i][rr(x)]=laz[i][x];
            laz[i][ll(x)]=laz[i][rr(x)]=laz[i][x];
        }
        laz[i][x]=0;
    }
    
    void change(int i,int x,int l,int r,int ls,int rs,int v)
    {
        if (l>rs||r<ls) return;
        if (l>=ls&&r<=rs) {
            sum[i][x]=v;
            if (!v) laz[i][x]=-1;
            else laz[i][x]=v;
            return;
        }
        if (laz[i][x]) pushdown(i,x);
        int mid=l+r>>1;
        if (ls<=mid) change(i,ll(x),l,mid,ls,rs,v);
        if (rs>mid) change(i,rr(x),mid+1,r,ls,rs,v);
        pushup(i,x);
    }
    
    int ask(int i,int x,int l,int r,int ls,int rs)
    {
        if (l>rs||r<ls) return 0;
        if (l>=ls&&r<=rs) return sum[i][x];
        if (laz[i][x]) pushdown(i,x);
        int mid=l+r>>1;
        return ask(i,ll(x),l,mid,ls,rs)+ask(i,rr(x),mid+1,r,ls,rs);
    }
    
    int main()
    {
        cin>>n>>t>>m;
        build(1,1,1,n);
        char s[3];int l,r,v;
        for (int i=1;i<=m;++i) {
            scanf("%s%d%d",s,&l,&r);
            if (l>r) swap(l,r);
            if (s[0]=='C') {
                scanf("%d",&v);
                for (int k=1;k<=t;++k)
                    if (k!=v)
                        change(k,1,1,n,l,r,0);
                    else change(k,1,1,n,l,r,1);
            }
            else {
                int ans=0;
                for (int k=1;k<=t;++k)
                    if (ask(k,1,1,n,l,r))
                        ++ans;
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    434. Number of Segments in a String 字符串中的单词个数
    C 递归
    Linux vi/vim
    CSS outline-style 属性
    Object.getPrototypeOf (Object) – JavaScript 中文开发手册
    Java 多线程编程
    HTML canvas strokeText() 方法
    HTML DOM Input Text readOnly 属性
    AngularJS ng-open 指令
    filecmp (File & Directory Access) – Python 中文开发手册
  • 原文地址:https://www.cnblogs.com/fushao2yyj/p/9512331.html
Copyright © 2020-2023  润新知