POJ 3225 线段树区间更新(两种更新方式)

http://blog.csdn.net/niuox/article/details/9664487

 

这道题明显是线段树,根据题意可以知道:

(用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)

U:把区间[l,r]覆盖成1

I:把[-∞,l)(r,∞]覆盖成0

D:把区间[l,r]覆盖成0

C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换

S:[l,r]区间0/1互换

 

这里有两个地方和区间更新不一样

一个是会更新选中区间以外的所有区域,可以这样子解决:

void update(char val,int L,int R,int l,int r,int rt)
{
    ...
    int mid = (l + r)>>1;
    if (L <= mid)
    {
        update(val,L,R,l,mid,rt<<1);
    }
    else if(val == 'I' || val == 'C')
    {
        a[rt<<1] = col[rt<<1] = 0;
    }
    if(R > mid)
    {
        update(val,L,R,mid+1,r,rt<<1|1);
    }
    else if(val == 'I' || val == 'C')
    {
        a[rt<<1|1] = col[rt<<1|1] = 0;
    }
}

 

if判断左边是否小于mid,如果不是,那么更新它的左边就是我们想要的选中区域外了,右边同理。

 

第二个是有两种更新方式,覆盖和异或

这种问题一般需要两种标记,但这里其中一种是覆盖,所以一种标记可以用值自身表示,-1表示杂,非-1表示纯。一个标记数组就行。

然后还要理清两种标记使用的方式

很明显我们可以知道这个性质:

当一个区间被覆盖后,不管之前有没有异或标记都没有意义了
所以当一个节点得到覆盖标记时把异或标记清空

 

第三种是开闭区间,这里可以通过把所有数乘2处理(偶数表示端点,奇数表示两端点间的区间)。

 

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 65535*2
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f

int n,m;

int a[MAXN<<4],col[MAXN<<4],ans;

bool vis[MAXN];

void FXOR(int x)
{
    if(a[x]!=-1) a[x]^=1;
    else col[x]^=1;
}


void PushDown(int rt)
{
    if(a[rt] != -1)
    {
        a[rt<<1] = a[rt<<1|1] = a[rt];
        col[rt<<1] = col[rt<<1|1] = 0;
        a[rt] = -1;
    }
    if(col[rt])
    {
        FXOR(rt<<1);
        FXOR(rt<<1|1);
        col[rt] = 0;
    }
}

void update(char val,int L,int R,int l,int r,int rt)
{
    if(L <= l && r <= R)
    {
        if(val == 'U')
        {
            a[rt] = 1;
            col[rt] = 0;
        }
        else if(val == 'D')
        {
            a[rt] = col[rt] = 0;
        }
        else if(val == 'C' || val == 'S')
        {
            FXOR(rt);
        }
        return;
    }
    PushDown(rt);
    int mid = (l + r)>>1;
    if (L <= mid)
    {
        update(val,L,R,l,mid,rt<<1);
    }
    else if(val == 'I' || val == 'C')
    {
        a[rt<<1] = col[rt<<1] = 0;
    }
    if(R > mid)
    {
        update(val,L,R,mid+1,r,rt<<1|1);
    }
    else if(val == 'I' || val == 'C')
    {
        a[rt<<1|1] = col[rt<<1|1] = 0;
    }
}

void query(int l,int r,int rt)
{
    if(a[rt] == 1)
    {
        for(int i = l;i<=r;i++) vis[i] = true;
        return;
    }
    else if(a[rt] == 0) return;
    if(l == r) return;
    PushDown(rt);
    int mid = (l + r)>>1;
    query(l,mid,rt<<1);
    query(mid+1,r,rt<<1|1);
}


int main()
{
    int r,t;
    char op,lchar,rchar;
    a[1] = col[1] = 0;
    while(~sf("%c %c%d,%d%c\n",&op,&lchar,&r,&t,&rchar))
    {
        r<<=1;
        t<<=1;
        if(lchar == '(') r++;
        if(rchar == ')') t--;
        update(op,r,t,0,MAXN,1);
    }
    query(0,MAXN,1);
    int s = -1,e;
    bool flag = false;
    for(int i=0;i<=MAXN;i++)
    {
        if(vis[i])
        {
            if(s == -1) s = i;
            e = i;
        }
        else
        {
            if(s!=-1)
            {
                if(flag) pf(" ");
                pf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');
                s = -1;
                flag = true;
            }
        }
    }
    if(!flag) printf("empty set");
    return 0;

}

 

posted @ 2016-08-04 17:46  qlky  阅读(1101)  评论(0编辑  收藏  举报