POJ 3225 Help with Intervals --线段树区间操作

题意:给你一些区间操作,让你输出最后得出的区间。

解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题。

线段树维护两个值: cov 和 rev  ,一个是覆盖标记,0表示此区间被0覆盖,1表示被1覆盖,-1表示未被覆盖, rev为反转标记,rev = 1表示反转,0表示不翻转

所以集合操作可以化为如下区间操作:

U l r:   把区间[l,r]覆盖成1
I  l r:   把[0,l)(r,MAX]覆盖成0
D l r:   把区间[l,r]覆盖成0
C l r:   把[0,l)(r,MAX]覆盖成0 , 且[l,r]区间0/1互换
S l r:   [l,r]区间0/1互换

重点在于pushdown函数以及边界处理。

代码:

#include <iostream>

#include <cmath>

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

using namespace std;

#define N (65536*2)



struct Tree

{

    int cov,rev;   //cov -1  rev 0

}tree[4*N];



struct ANS

{

    char L,R;

    int A,B;

}ans[N+1];

int cnt;



void build(int l,int r,int rt)

{

    tree[rt].cov = 0;

    tree[rt].rev = 0;

    if(l == r) return;

    int mid = (l+r)/2;

    build(l,mid,2*rt);

    build(mid+1,r,2*rt+1);

}



void pushdown(int l,int r,int rt)

{

    if(tree[rt].cov != -1)

    {

        tree[2*rt].cov = tree[2*rt+1].cov = tree[rt].cov;

        tree[2*rt].rev = tree[2*rt+1].rev = 0;

        tree[rt].cov = -1;

    }

    if(tree[rt].rev)

    {

        if(tree[2*rt].cov != -1)

            tree[2*rt].cov ^= 1;

        else

            tree[2*rt].rev ^= 1;



        if(tree[2*rt+1].cov != -1)

            tree[2*rt+1].cov ^= 1;

        else

            tree[2*rt+1].rev ^= 1;

        tree[rt].rev = 0;

    }

}



void update(int l,int r,int aa,int bb,int op,int rt)

{

    if(aa > bb || aa < 0) return;    //必须要加,否则会RE

    if(aa <= l && bb >= r)

    {

        if(op != 2)   //cover to 0/1

        {

            tree[rt].cov = op;

            tree[rt].rev = 0;

        }

        else          //op == 2  reverse

        {

            if(tree[rt].cov != -1)

                tree[rt].cov ^= 1;

            else

                tree[rt].rev ^= 1;

        }

        return;

    }

    pushdown(l,r,rt);

    int mid = (l+r)/2;

    if(aa <= mid)

        update(l,mid,aa,bb,op,2*rt);

    if(bb > mid)

        update(mid+1,r,aa,bb,op,2*rt+1);

}



void query(int l,int r,int rt)

{

    if(tree[rt].cov == 1)

    {

        ans[cnt].L = (l%2==1)?'(':'[';

        ans[cnt].A = l/2;

        ans[cnt].R = (r%2==1)?')':']';

        ans[cnt].B = (r+1)/2;

        cnt++;

    }

    else if(tree[rt].cov == 0) return;

    else

    {

        pushdown(l,r,rt);

        int mid = (l+r)/2;

        query(l,mid,2*rt);

        query(mid+1,r,2*rt+1);

    }

}



void print()

{

    char nowl,nowr;

    int nowA,nowB;

    if(cnt == 0)

        puts("empty set");

    else

    {

        nowl = ans[0].L;

        nowr = ans[0].R;

        nowA = ans[0].A;

        nowB = ans[0].B;

        for(int i=1;i<cnt;i++)

        {

            if(ans[i].A == nowB && (nowr == ']' || ans[i].L == '['))

            {

                nowB = ans[i].B;

                nowr = ans[i].R;

            }

            else

            {

                printf("%c%d,%d%c ",nowl,nowA,nowB,nowr);

                nowl = ans[i].L;

                nowr = ans[i].R;

                nowA = ans[i].A;

                nowB = ans[i].B;

            }

        }

        printf("%c%d,%d%c\n",nowl,nowA,nowB,nowr);

    }

}



int main()

{

    int a,b;

    char L,R,op;

    int n = 65536*2;

    build(0,n,1);

    while(scanf("%c %c%d,%d%c\n",&op,&L,&a,&b,&R)!=EOF) // '\n' 务必要加

    {

        a = 2*a; if(L == '(') a++;

        b = 2*b; if(R == ')') b--;

        if(a > b || a < 0) continue;

        if(op == 'U')  //并集

            update(0,n,a,b,1,1);

        else if(op == 'I')

        {

            update(0,n,0,a-1,0,1);

            update(0,n,b+1,n,0,1);

        }

        else if(op == 'D')

            update(0,n,a,b,0,1);

        else if(op == 'C')

        {

            update(0,n,0,a-1,0,1);

            update(0,n,b+1,n,0,1);

            update(0,n,a,b,2,1);

        }

        else

            update(0,n,a,b,2,1);

    }

    cnt = 0;

    query(0,n,1);

    print();

    return 0;

}
View Code

 

参考文章: http://my.oschina.net/llmm/blog/124256

你可能感兴趣的:(with)