POJ 3225


POJ 3225

有中文题意,不用多说,以前刚学线段树的时候曾经做过,不过死活做不过来,现在还是无限TLE,实在没办法了,稍微去瞄了其他人的代码,豁然开朗啊,稍微修改一下就AC了。

有5种操作,实质上针对线段树,只有2种操作,1是更新,二是翻转。

U : 更新a,b段为1。

I : 更新除a,b段之外的所有区间为0。

D :更新a,b段为0。

C : 翻转a,b段,a,b段之外的区间更新为0。

S : 翻转a,b段。

将整数以外的每个区间都看成一个整数,就可以建立一个65535*2 + 1长度的线段树。线段树保存2个值,一个是更新值,一个是翻转次数。每作一次更新操作时候,更新的区间的翻转次数要清0,翻转操作时候,只需要将区间操作数+1,等输入完毕后再一次过处理,就可以大大省略时间,就是蠢在这里了,连翻转每次都处理一次。

 

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
using namespace std;
#define LL long long
#define inf 0x7ffffff
#define L(x) x<<1
#define R(x) x<<1|1
#define M(x,y) (x + y)>>1
#define B(x) x>>1
#define N 150000
int flag[N];
char x,l,z,r;
int a,b,y;
struct st
{
	int l,r;
	int nots;
	int mark;
}t[N*4];
void change(int n,int l,int r);
void build(int n,int l,int r)
{
	t[n].l = l;
	t[n].r = r;
	t[n].mark = t[n].nots = 0;
	if(l == r)
		return ;
	int mid = M(l,r);
	build(L(n),l,mid);
	build(R(n),mid + 1,r);
}
void clear(int n)
{
	if(t[n].l != t[n].r)
	{
		t[L(n)].nots = t[R(n)].nots = -1;
	}
}
void down(int n)
{
	if(t[n].mark != -1)
	{
		t[L(n)].mark = t[R(n)].mark = t[n].mark;
		t[n].mark = -1;
	}
	if(t[n].nots == -1)
	{
		t[L(n)].nots = t[R(n)].nots = -1;
		t[n].nots = 0;
	}
	else
	{
		if(t[L(n)].nots == -1)
		{
			t[L(n)].nots = t[n].nots;
			clear(L(n));
		}
		else
			t[L(n)].nots += t[n].nots;
		if(t[R(n)].nots == -1)
		{
			t[R(n)].nots = t[n].nots;
			clear(R(n));
		}
		else
			t[R(n)].nots += t[n].nots;
		t[n].nots = 0;
	}
}
void up(int n)
{
	if(t[L(n)].mark == t[R(n)].mark && t[L(n)].mark != -1 )
	{
		t[n].mark = t[L(n)].mark;
	}
}
void renew(int n,int l,int r,int v)
{
	if(t[n].l >= l && t[n].r <= r )
	{
		t[n].mark = v;
		t[n].nots = -1;
		return ;
	}
	down(n);
	int mid = M(t[n].l,t[n].r);
	if(l <= mid)
		renew(L(n),l,r,v);
	if(r > mid)
		renew(R(n),l,r,v);
	up(n);
}
void change(int n,int l,int r)
{
	if(t[n].l >= l && t[n].r <= r)
	{
		if(t[n].nots == -1)
		{
			t[n].nots = 1;
			if(t[n].l != t[n].r)
			{
				t[L(n)].l = t[R(n)].r = -1;
			}
		}
		else
			t[n].nots ++;
		return ;
	}
	down(n);
	int mid = M(t[n].l,t[n].r);
	if(l <= mid)
		change(L(n),l,r);
	if(r > mid)
		change(R(n),l,r);
	up(n);
}
void deal(int n)
{
	if(t[n].l == t[n].r)
	{
		flag[t[n].l] = (t[n].mark + t[n].nots)%2;
		return ;
	}
	down(n);
	deal(L(n));
	deal(R(n));
}
void show()
{
	int y = -1;
	for(int i = 0,a = b = -1;i <= 65535*2;i++)
	{
		if(flag[i] == 1)
		{
			if(a == -1)
			{
				a = b = i;
			}
			else
				b++;
		}
		else
		{
			if(a != -1)
			{
				if(y == -1)
				{
					y = 1;
				}
				else
					printf(" ");
				if(a%2 == 0)
					printf("[%d,",a/2);
				else
					printf("(%d,",a/2);
				if(b%2 == 0)
					printf("%d]",b/2);
				else
					printf("%d)",(b + 1)/2);
			}
			a = b = -1;
		}
	}
	if(y == -1)
		puts("empty set");
	else
		printf("\n");
}
int main()
{
	int a,b;
	memset(flag , 0, sizeof(flag));
	build(1,0,65535*2);
	while( cin>>x )
	{
		cin>>l;
		scanf("%d,%d",&a,&b);
		cin>>r;
		a = a*2;
		b = b*2;
		if(l == '(')
			a++;
		if(r == ')')
			b--;
		if(a > b)
			continue;
		if(x == 'U')
		{
			renew(1,a,b,1);
		}
		if(x == 'I')
		{
			if(a != 0)
				renew(1,0,a - 1,0);
			if(b != 65535*2)
				renew(1,b + 1,65535*2,0);
		}
		if(x == 'D')
		{
			renew(1,a,b,0);
		}
		if(x == 'C')
		{
			if(a != 0)
				renew(1,0,a - 1,0);
			if(b != 65535*2)
				renew(1,b + 1,65535*2,0);
			change(1,a,b);
		}
		if(x == 'S')
		{
			change(1,a,b);
		}
	}
	deal(1);
	show();
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值