您的位置:首页 > 其它

POJ 3225 Help with Intervals

2015-09-17 23:23 369 查看
题目链接:http://poj.org/problem?id=3225&lang=zh-CN&change=true

题意:对一个区间进行5种操作,问最后覆盖区间

1.U T 当前区间并上区间T

2. I T 当前区间交上区间T

3.D T 将当前区间和区间T的交去掉

4.C T 将T区间中与当前区间的交去掉

5.S T DT并上CT

思路:可以想到每种操作就是对区间更新,和之前的题目一样使用lazy标记就可以做到,lazy标志不会一直重叠,区间就只有3种情况:被覆盖(lazy==1).没有被覆盖(lazy==0),以及部分覆盖(lazy==-1),不一样的地方某些操作会将区间覆盖翻转(覆盖变成未覆盖,未覆盖变成覆盖),需要用到翻转标记,当lazy标记下传的时候根据翻转标记的奇偶性进行改变;还有注意的是D(3,4)一类的普通的线段树进行更新查询出现[l,2]和[5,r]的情况,和答案[l,3)和(4,r]不一样,也就是说我们没有办法判断开闭区间,这个时候我们要把l和r乘2,如果是(l,r)的话,l++以及r--,最后在判断奇偶性就可以知道是开闭区间了……

将5种操作翻译一下:

1. 将T区间覆盖

2. 将T以外的地方清空

3. 将T区间清空

4.将T区间以外的地方清空,T区间内原来覆盖的地方覆盖,覆盖的地方清空

5.操作3与操作4的并,也就是T区间进行翻转

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 65835*2
using namespace std;

struct Tree
{
int l,r;
}tree[maxn*4];

int lazy[maxn*4],turn[maxn*4],res_l[maxn],res_r[maxn];
int cnt=0;

void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if (l==r) return;

int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
}

void pushdown(int root)
{
if (lazy[root]!=-1)
{
if (turn[root]%2==1) lazy[root]=!lazy[root];
lazy[root<<1]=lazy[root<<1|1]=lazy[root];
turn[root<<1]=turn[root<<1|1]=turn[root]=0;
lazy[root]=-1;
}

if (turn[root]%2==1)
{
turn[root<<1]++;
turn[root<<1|1]++;
turn[root]=0;
}
}

void update(int root,int l,int r,int val,int k)
{
if (tree[root].l>=l && tree[root].r<=r)
{
if (k==1)
{
lazy[root]=val;
turn[root]=0;
}
else turn[root]++;
return;
}
pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;
if (l<=mid) update(root<<1,l,r,val,k);
if (r>mid) update(root<<1|1,l,r,val,k);
}

void que(int root,int l,int r)
{
if (lazy[root]!=-1)
{
if (turn[root]%2==1)
{//cout<<":"<<lazy[root]<<endl;
lazy[root]=!lazy[root];
turn[root]=0;
}

if (lazy[root]==1)
{//cout<<tree[root].l<<":"<<":"<<tree[root].r<<endl;
res_l[cnt]=tree[root].l;
res_r[cnt]=tree[root].r;
cnt++;
}
return;
}

if (tree[root].l==tree[root].r) return;
pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;

if (l<=mid) que(root<<1,l,r);
if (r>mid) que(root<<1|1,l,r);
}

int main()
{
char op,ll,rr;
int l,r;
build(1,0,maxn-1);
memset(lazy,0,sizeof(lazy));
memset(turn,0,sizeof(turn));
cnt=0;
while (scanf("%c %c%d,%d%c",&op,&ll,&l,&r,&rr)!=EOF)
{
l*=2;
r*=2;
if (ll=='(') l++;
if (rr==')') r--;
if (op=='U')
{//cout<<l<<":"<<r<<endl;
if (l<=r)
update(1,l,r,1,1);
}
else if (op=='I')
{
if (l>0)
update(1,0,l-1,0,1);
update(1,r+1,maxn-1,0,1);
}
else if (op=='D')
{
if (l<=r)
update(1,l,r,0,1);
}
else if (op=='C')
{
if (l>0)
update(1,0,l-1,0,1);
update(1,r+1,maxn-1,0,1);
if (l<=r)
update(1,l,r,0,0);
}
else if (op=='S')
{
if (l<=r)
update(1,l,r,0,0);
}
getchar();

}
que(1,0,maxn-1);
if (cnt!=0)
{
for (int i=0;i<cnt;i++)
{
int tem=i;
while (i<cnt-1 && res_r[i]==res_l[i+1]-1)
i++;

int st=res_l[tem],ed=res_r[i];

if (st%2==0) printf("[%d,",st/2);
else printf("(%d,",st/2);

if (ed%2==0) printf("%d] ",ed/2);
else printf("%d) ",(ed+1)/2);
}
}
else printf("empty set");
printf("\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: