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;
}