zoukankan      html  css  js  c++  java
  • 洛谷P2161 线段树染色 SHOI2009 会场预约

    题目链接:https://www.luogu.org/problem/P2161

    题意:有两种操作,操作A是在区间l,r上染色(每次染的颜色都不同),同时输出那些与之重叠的颜色的个数并将该颜色完全清空,操作B是统计区间目前还有多少种颜色。

    分析:用线段树来做,只用到区间修改,每次修改时都找到只有一种颜色的区间,如果这个颜色还没被删除,就计数并删除。删除可以直接用一个del数组来实现

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=2e5+7;
    #define ls rt<<1
    #define rs rt<<1|1
    int cnt=0;//当前颜色的编号
    int ans=0;//记录此时还有多少种颜色
    int res;//记录一次A操作删去了多少种颜色 
    struct node{
        char opt[2];
        int l,r;
    }a[maxn];
    bool same[maxn<<2];//代表该区间内是否同色,1为同色 
    int tag[maxn<<2];//lazy标记,记录的是颜色 
    bool del[maxn];//用来标记一种颜色是否被删除 
    void build(int rt,int l,int r){
        same[rt]=1;tag[rt]=0;
        if(l==r) return ;
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
    }
    void pushdown(int l,int r,int rt){
        same[rt]=0;//关键!!!!
        //能下传就说明一定不是同色 
        if(!tag[rt])return;
        //标记下放 
        tag[ls]=tag[rs]=tag[rt];
        tag[rt]=0;
    }
    void find(int l,int r,int rt){
        if(same[rt]==1){
            if(!del[tag[rt]]&&tag[rt]) ans--,res++;
            del[tag[rt]]=1;
            tag[rt]=cnt;//记录颜色
            return; 
        }
        int mid=(l+r)>>1;
        find(l,mid,ls);find(mid+1,r,rs);
        same[rt]=1;tag[rt]=cnt;
    }
    void modify(int l,int r,int s,int t,int rt){
        if(s<=l&&r<=t){
            find(l,r,rt);
            return ;
        }
        pushdown(l,r,rt);
        int mid=(l+r)>>1;
        if(s<=mid) modify(l,mid,s,t,ls);
        if(t>mid)  modify(mid+1,r,s,t,rs);
    }
    int main(){
        int n;scanf("%d",&n);
        int st=inf,ed=0;//记录左右端点 
        for(int i=1;i<=n;i++){
            scanf("%s",a[i].opt);
            if(a[i].opt[0]=='A'){
                scanf("%d%d",&a[i].l,&a[i].r);
                st=min(st,a[i].l);ed=max(ed,a[i].r);
            }
        }
        build(1,st,ed);
        for(int i=1;i<=n;i++){
            if(a[i].opt[0]=='A'){
                ++ans;++cnt;res=0;
                modify(st,ed,a[i].l,a[i].r,1);
                printf("%d
    ",res);
            }
            else printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    一种不求交点确定直线与三角形是否相交的方法
    碰撞边界锯齿的平滑方法
    demo的凹凸贴图效果
    MySQL进阶篇触发器
    MySQL进阶篇索引
    Maven的POM文件详解
    Swagger
    MySQL进阶篇存储过程
    SpringBoot基础篇
    MySQL基础篇多表操作
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11455804.html
Copyright © 2011-2022 走看看