poj3777(线段树成段覆盖)

来源:互联网 发布:一键部署php环境 编辑:程序博客网 时间:2024/06/08 19:38

题目链接:poj3777

/*poj 2777 Count Color 线段树成段覆盖,lazy题目大意:一段区间,初始值为1,两种操作,一种是修改,一种是查询思路:线段树区间成段覆盖建树是每个节点的标记color,初始值为1涂色覆盖时,若完全覆盖,则color为颜色编号,若覆盖一部分,则先将标记下放左右儿子,再将标号标记为-1表示此节点被部分覆盖过。*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100005int n,color;struct node{    int l,r;    int color;}s[N<<2];int ans[33];void build(int l, int r, int n){    s[n].l = l;    s[n].r = r;    s[n].color = 1;    if(l == r) return;    int mid = (l+r) >> 1;    build(l, mid, n<<1);    build(mid + 1, r, n<<1|1);}void update(int l, int r, int n){    if(s[n].color == color) return;    if(s[n].l == l && s[n].r == r)    {        s[n].color = color;        return;    }    if(s[n].color != -1)    {        s[n<<1].color = s[n<<1|1].color = s[n].color;        s[n].color = -1;    }    int mid = (s[n].l + s[n].r) >> 1;    if(r <= mid)        update(l, r, n<<1);    else if(l > mid)        update(l, r, n<<1|1);    else    {        update(l, mid, n<<1);        update(mid+1, r, n<<1|1);    }}void query(int l, int r, int n){    if(s[n].color != -1 )    {        ans[ s[n].color ] ++;        return;    }    int mid = (s[n].l + s[n].r) >> 1;    if(r <= mid)        query(l, r, n<<1);    else if(l > mid)        query(l, r, n<<1|1);    else    {        query(l, mid, n<<1);        query(mid+1, r, n<<1|1);    }}int main(){int i,m,x,y,t,tot;char ch[2];while(~scanf("%d%d%d",&m,&tot,&t)){    build(1,m,1);    while(t--)    {        scanf("%s",ch);        if(ch[0] == 'C')        {            scanf("%d%d%d",&x,&y,&color);            if(x > y) swap(x,y);            update(x,y,1);        }        else if(ch[0] == 'P')        {            memset(ans, 0, sizeof(ans));            scanf("%d%d",&x,&y);            if(x > y) swap(x,y);            query(x,y,1);            int sum = 0;            for(int j = 1; j <= 30; j ++)            if(ans[j]) sum++;            printf("%d\n",sum);        }    }}return 0;}


原创粉丝点击