POJ-3225 Help with Intervals-线段树/成段更新+倍增区间法

来源:互联网 发布:最长公共子序列c语言 编辑:程序博客网 时间:2024/04/28 22:41

题意:给一个0-65535的区间,区间端点为L,R 区间有开区间闭区间之分,一开始你拥有一个S区间,为全空的区间

n次操作,每次操作有4种,

U: 把T区间L,R覆盖成1 (S U T)

I:把求给出T区间,求S和T交集,也就是把[-∞,l)(r,∞]覆盖成0

D:用原区间S减去所给区间T,也就是把 区间T置为零

C:用所给区间T减去S,然后把结果赋值给S,也就是把把[-∞,l)(r,∞]覆盖成0,把【l,r】取反

S:求异或,直接把区间【l,r】取反


上面的操作都可以用线段树的区间更新完成,分别是一个set操作,和一个求异或的操作,我们下放延迟标记的时候,注意分清先后,先下放set操作,并且set操作之后需要清空异或标记。

对于异或操作,如果当前节点有set标记,那么只需要把set标记取反即可,如果没有set标记则取反异或标记

还有一个很关键的问题是开闭区间的问题,我们用倍增区间法来解决此问题

(l, r) --> [2 * l + 1, 2 * r - 1](l, r] --> [2 * l + 1, 2 * r][l, r) --> [2 * l, 2 * r - 1][l, r] --> [2 * l, 2 *r]

我们用偶数点代表整数点,奇数点代表两个整数点之间的 所有非整数点,那么问题便解决了.

直接把端点乘2,左开则l++,右开则r--, 处理完后  最后输出 的端点为 l/2 (r+1)/2   如果l或r为奇数,对应开区间,反之闭区间



<span style="font-size:14px;">#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;#define ptf(ar1,ar2)  printf("%d:%d\n",ar1,ar2);typedef __int64 ll;const ll maxn = 131570+500;int vis[131570+500]; struct tree{int  set[maxn*4],yihuo[maxn*4];void pd_set(int i,int l,int r){ if (set[i]!=-1){set[i<<1]=set[i<<1|1]=set[i]; yihuo[i<<1]=yihuo[i<<1|1]=yihuo[i]=0; set[i]=-1;} if (yihuo[i]){if (set[i<<1]!=-1) set[i<<1]^=1;else yihuo[i<<1]^=1;if (set[i<<1|1]!=-1) set[i<<1|1]^=1;elseyihuo[i<<1|1]^=1;yihuo[i]=0;  }}void update(int l,int r,int ql,int qr,int i,int val,int op){if (ql>r||qr<l) return ;if (ql<=l&&qr>=r){ if (op){if (set[i]!=-1) set[i]^=1;else yihuo[i]^=1; }else{set[i]=val; yihuo[i]=0;}return ;}pd_set(i,l,r); int m=(l+r)>>1;update(l,m,ql,qr,i<<1,val,op);update(m+1,r,ql,qr,i<<1|1,val,op); } void init(){//memset(sum,0,sizeof(sum));//memset(yihuo,0,sizeof(yihuo));//memset(set,-1,sizeof(set));}int query2( int l,int r,int i){ if  (l==r){if (set[i]==1) vis[r]=1;return 0;}pd_set(i,l,r);int mid=(l+r)>>1;query2(l,mid,i<<1); query2(mid+1,r,i<<1|1);}};tree tp ;int main(  ){    char op;    int l,r;    char lrat,rrat;    tp.init();while(scanf("%c %c%d,%d%c",&op,&lrat,&l,&r,&rrat)!=EOF)    {getchar();        l*=2;        r*=2;        if (lrat=='(') l++;        if (rrat==')') r--;        if (op=='U')            tp.update(0,131570,l,r,1,1,0);        if (op=='I')         {            tp.update(0,131570,0,l-1,1,0,0);            tp.update(0,131570,r+1,131570,1,0,0);        }        if (op=='D')            tp.update(0,131570,l,r,1,0,0);        if (op=='C')        {            tp.update(0,131570,0,l-1,1,0,0);            tp.update(0,131570,r+1,131570,1,0,0);            tp.update(0,131570,l,r,1,1,1);        }        if (op=='S')            tp.update(0,131570,l,r,1,1,1);    }int i;tp.query2(0,131570 ,1);    int line=0;    int exist=0;    for(  i=0; i<=131570 ; i++)    {        if (vis[i])        {            exist=1;            if (line)  printf(" ");            int j=i+1;            while(vis[j]&&j<=131570) j++;            j--;            if (i%2) printf("(");            else printf("[");            printf("%d,%d",i/2,(j+1)/2);            if (j%2)                printf(")");            else                printf("]");            line=1;            i=j;        }    }if (exist==0)printf("empty set");printf("\n");return 0;}</span>


0 0