poj 3225(线段树)

来源:互联网 发布:vue.js 分页插件 编辑:程序博客网 时间:2024/05/22 02:30

题目链接:http://poj.org/problem?id=3225


题意描述:给你一个集合初始化为空集,然后让它和其他集合进行一系列操作,最后输出操作之后的集合,集合操作有U表示求并集,I表示求交集,D表示S与给出集合求差集,C表示给出集合与S的集合求差集,这里的区间有开有并


分析:假设不考虑区间的开与闭,用线段树来维护所有区间初始化为0

如果是U的话则将(l,r)的值赋值为1

如果是I的话则将(0,l-1)和(r+1,max)的值赋值为1

如果是D的话则将(l,r)赋值为0

如果是C的话则将(0,l-1)(r+1,max)的值赋值为0,将区间(l,r)的区间取反

如果是S的话则将(l,r)区间取反


但是这样都是建立在点树的基础上的,但这里单位区间和点都应该看成点,这里就需要一个转换左闭区间转换为点2*l,将左开区间转换为2*r+1,将右闭区间转换为2*r,将右开区间转换为2*r-1,那么这样之后所有的单位区间为一个点,点也是一个点,这样就可以用线段树来维护啦,具体见代码:


#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N=65535*2;struct node{    int l,r;    int tag;    int num;}tree[N*4];bool vis[N];void bulid (int rt, int l , int r){    tree[rt].l=l;    tree[rt].r=r;    tree[rt].tag=0;    tree[rt].num=0;    if(l==r)return;    int mid=(l+r)>>1;    bulid(2*rt,l,mid);    bulid(2*rt+1,mid+1,r);}void pushdown(int rt){    if(tree[rt].tag!=-1)    {        tree[2*rt].tag=tree[rt].tag;        tree[2*rt+1].tag=tree[rt].tag;        tree[rt].tag=-1;        tree[2*rt].num=tree[2*rt+1].num=tree[rt].num=0;    }    if(tree[rt].num)    {        if(tree[2*rt].num)        tree[2*rt].num=0;        else if(tree[2*rt].tag!=-1) tree[2*rt].tag^=1;        else tree[2*rt].num=1;        if(tree[2*rt+1].num)tree[2*rt+1].num=0;        else if(tree[2*rt+1].tag!=-1) tree[2*rt+1].tag^=1;        else tree[2*rt+1].num=1;        tree[rt].num=0;    }}void insert(int rt, int l , int r, int op){     //if(tree[rt].l>l||tree[rt].r<r)return;    if(op<2)    {        if(tree[rt].l==l&&tree[rt].r==r)        {            tree[rt].tag=op;            tree[rt].num=0;            return;        }    }    else if(op==2)    {        if(l==tree[rt].l && r==tree[rt].r)        {            if(tree[rt].tag!=-1)            tree[rt].tag^=1;            else tree[rt].num^=1;            return;        }    }    int mid=(tree[rt].l+tree[rt].r)>>1;    pushdown(rt);    if(r<=mid)insert(2*rt,l,r,op);    else if(l>mid)insert(2*rt+1,l,r,op);    else {insert(2*rt,l,mid,op); insert(2*rt+1,mid+1,r,op);}    if(tree[2*rt].tag==tree[2*rt+1].tag)    tree[rt].tag=tree[2*rt].tag;}void quary(int rt){    if(tree[rt].l==tree[rt].r)    {        vis[tree[rt].l]=tree[rt].tag;        return;    }    pushdown(rt);    quary(2*rt);    quary(2*rt+1);}int main (){    char op, ch1, ch2;    int l,r,i,s;    bulid(1,0,N);    while(scanf("%c %c%d,%d%c",&op,&ch1,&l,&r,&ch2)!=EOF)    {        getchar();        l=l+l;        r=r+r;        if(ch1=='(')           l++;        if(ch2==')')        r--;        if(l>r)continue;        switch(op)        {            case 'U':            insert(1,l,r,1);break;            case 'I':            if(l>0)            insert(1,0,l-1,0);            if(r<N)            insert(1,r+1,N,0);break;            case 'D':            insert(1,l,r,0);break;            case 'C':            if(l>0)            insert(1,0,l-1,0);            if(r<N)            insert(1,r+1,N,0);            insert(1,l,r,2);break;            case 'S':            insert(1,l,r,2);break;        }    }    quary(1);     int begin, end, tmp = 1;    for(i = 0; i <= N; i++)    {        while(i <= N && !vis[i])   i++;        begin = i;        if(i > N)    break;        while(i <= N && vis[i])    i++;        end = i - 1;        tmp = 0;        if(begin&1)            printf("(%d,", begin/2);         else            printf("[%d,", begin/2);        if(end&1)            printf("%d) ", (end+1)/2);        else            printf("%d] ", end/2);    }    if(tmp)        printf("empty set");    printf("\n");    return 0;}


原创粉丝点击