poj2777线段树+lazy思想

来源:互联网 发布:本溪 农业 盘古网络 编辑:程序博客网 时间:2024/05/21 08:42

题意:有一个长板子,多次操作,有两种操作,第一种是给从a到b那段染一种颜色c,另一种是询问a到b有多少种不同的颜色。

 

这题更加让我理解线段树的结构了,特别是lazy思想的运用。

事实上lazy思想就是个懒人的标记,若对于这个结点lazy标记为true,就代表不需要继续查找缩小的区间了。

主要是在更新结点的地方,若填充整个区间时,标记lazy,则在下次其他的更新操作时,若结点为ture,则在更新操作中。

为了控制标记,取消原来结点的标记false,表示此节点不可用,即该结点代表的线段中有不同的取值,然后在左右子树中标记lazy,直到填充整个区间。

 

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define maxn 100004struct Node{    int color;    int l, r;    Node *pleft, *pright;    bool end;} tree[maxn * 3];int n, t, o, ncount;void buildtree(Node *proot, int l, int r){    proot->l = l;    proot->r = r;    proot->color = 1;    proot->end = true;    if (l == r)        return;    int mid = (l + r) / 2;    ncount++;    proot->pleft = tree + ncount;    ncount++;    proot->pright = tree + ncount;    buildtree(proot->pleft, l, mid);    buildtree(proot->pright, mid + 1, r);}void paint(Node *proot, int l, int r, int color){    if (proot->l == l && proot->r == r)    {        proot->end = true;        proot->color = color;        return;    }    if (proot->end)                     //lazy思想,当一次取整块lr区间时,标记end,    {                                   //然后下次操作遇到lr区间但不是目标区间时,消去该节点的end标记        proot->end = false;             //为了简化后面的操作,直接给左右子树进行相应操作并同意标记end        proot->pleft->color = proot->color;        proot->pleft->end = true;        proot->pright->color = proot->color;        proot->pright->end = true;    }    int mid = (proot->l + proot->r) / 2;    if (r <= mid)        paint(proot->pleft, l, r, color);    else if(l > mid)    paint(proot->pright, l, r, color);    else    {        paint(proot->pleft, l, mid, color);        paint(proot->pright, mid +1, r, color);    }    proot->color = proot->pleft->color | proot->pright->color;  //位运算}int query(Node *proot, int l, int r){    if (proot->end)             //若父节点已经被标记.便不需要往下找        return proot->color;    if (proot->l == l && proot->r == r)        return proot->color;    int mid = (proot->l + proot->r) / 2;    if (r <= mid)        return query(proot->pleft, l, r);    else if(l > mid)    return query(proot->pright, l, r);    return query(proot->pleft, l, mid) | query(proot->pright, mid + 1, r);}int countbit(int a){    int x = 1;    int ret = 0;    for (int i = 0; i < 32; i++, x <<= 1)        if (x & a)            ret++;    return ret;}int main(){//    freopen("t.txt", "r", stdin);    ncount = 0;    scanf("%d%d%d", &n, &t, &o);    getchar();    buildtree(tree, 1, n);    for (int i = 0; i < o; i++)    {        char order;        int l, r, c;        scanf("%c", &order);        if (order == 'C')        {            scanf("%d%d%d", &l, &r, &c);            if (l > r)                swap(l, r);            paint(tree, l, r, 1 << (c - 1));        }        else        {            scanf("%d%d", &l, &r);            if (l > r)                swap(l, r);            printf("%d\n", countbit(query(tree, l, r)));        }        getchar();    }    return 0;}


 

原创粉丝点击