[POJ2777] 统计颜色 - 线段树

来源:互联网 发布:环境破坏的事例和数据 编辑:程序博客网 时间:2024/05/17 01:08

题目描述

有一个长度为L厘米板,L是一个正整数,所以我们可以把它均匀地划分成L个部分,分别从左到右编号为1,2……L,每一个部分长度都为1厘米。现在我们必须给每个部分涂色,一个部分一种颜色,要求完成以下两种操作:
  1.“C A B C1”:表示从A部分到B部分涂上C1颜色。
  2.“P A B”:表示从A部分到B部分涂了几种颜色。
  在我们的日常生活中,我们有非常少几种颜色(红色,绿色,蓝色,黄色…),所以你可以假设不同颜色的总数T是非常少。简单地说,我们表示颜色的名称为颜色1,颜色2,…..颜色T。最初时候,这个厘米版都涂成颜色1。


输入格式

输入文件的第一行包含三个整数L(1<=L<=10^5),T(1<=T<=30)和M(1<=M<=10^5)。M表示操作的次数。
以下M行,每行包含“C A B C1”或者“P A B”(A,B,C1都是整数,A可以比B大)。


输出格式

输出文件依顺序输出,每行一个数字。


样例数据

样例输入

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

样例输出

2
1


题目分析

线段树,维护当前线段的颜色
懒标记一下,找到就退。
将颜色状压塞进线段树里面,可以节约时间。


源代码

#include<algorithm>#include<iostream>#include<iomanip>#include<cstring>#include<cstdlib>#include<vector>#include<cstdio>#include<cmath>#include<queue>using namespace std;inline const int Get_Int() {    int num=0,bj=1;    char x=getchar();    while(x<'0'||x>'9') {        if(x=='-')bj=-1;        x=getchar();    }    while(x>='0'&&x<='9') {        num=num*10+x-'0';        x=getchar();    }    return num*bj;}const int maxn=100000;struct Tree {    int left,right,color,sum;};struct Segment_Tree {    Tree tree[maxn*4];    int ans;    void build(int index,int Left,int Right) {        tree[index].left=Left;        tree[index].right=Right;        tree[index].color=tree[index].sum=1;        if(Left==Right)return;        int mid=(Left+Right)/2;        build(2*index,Left,mid);        build(2*index+1,mid+1,Right);    }    void push_down(int index) { //标记下传,下传当前lazy        if(!tree[index].color)return;        tree[index*2].sum=tree[index*2+1].sum=tree[index].sum;        tree[index*2].color=tree[index*2+1].color=tree[index].color;        tree[index].color=0;    }    void push_up(int index) { //标记上传,合并子树信息        tree[index].sum=tree[index*2].sum|tree[index*2+1].sum;    }    void modify(int index,int Left,int Right,int data) {        if(Right<tree[index].left||Left>tree[index].right)return; //不相交        if(Left<=tree[index].left&&Right>=tree[index].right) { //完全包含            tree[index].color=tree[index].sum=data;            return;        }        push_down(index); //标记下传        modify(index*2,Left,Right,data);        modify(index*2+1,Left,Right,data);        push_up(index); //标记上传    }    void init() {        ans=0;    }    void Query(int index,int Left,int Right) {        if(Right<tree[index].left||Left>tree[index].right)return; //不相交        if(Left<=tree[index].left&&Right>=tree[index].right) { //完全包含            ans|=tree[index].sum;            return;        }        push_down(index); //标记下传        Query(index*2,Left,Right);        Query(index*2+1,Left,Right);        push_up(index); //标记上传    }};Segment_Tree st;int n,cn,m;int main() {    scanf("%d%d%d",&n,&cn,&m);    st.build(1,1,n);    for(int i=1; i<=m; i++) {        char order;        getchar();        scanf("%c",&order);        if(order=='C') {            int Left,Right,color;            scanf("%d%d%d",&Left,&Right,&color);            if(Left>Right)swap(Left,Right);            st.modify(1,Left,Right,1<<(color-1));        } else {            int Left,Right;            scanf("%d%d",&Left,&Right);            if(Left>Right)swap(Left,Right);            st.init();            st.Query(1,Left,Right);            int cnt=0,tmp=st.ans;            while(tmp) {                if(tmp&1)cnt++;                tmp>>=1;            }            printf("%d\n",cnt);        }    }    return 0;}

0 0
原创粉丝点击