POJ 3225 Help with Intervals(线段树)

  这题纠结了两天,开始一点思路没有,后来看到有大牛把这题的做法称作区间树,并说明了区间树与线段树的区别(区间树是区间内被染色的区间标记为1,未被染色的区间标记为0)。我觉得这就是线段树的一类操作,没有必要分出去吧。。。

思路:区间更新,首先想到的应该是Lazy思想;这题分五种情况:

CommandSemantics
U T S  S  T
I T S  S  T
D T S  S  T
C T S  T  S
S T S  S  T

U:直接将T对应的区间覆盖为1;

I:将T的补区间(比如T[l, r], 补区间就是[0, l-1], [r+1, N])清零即可;

D:直接将T区间清零;

C:先将T的补区间清零,再对T区间取反;

S:直接对T区间取反;

(把这几个操作在纸上写写,马上就明白了。)

然后就是剩下的线段树的区间更新、区间上传、区间下分了。

Code:

#include <iostream>
#include
<cstdio>
#include
<cstring>
#define L(t) t << 1
#define R(t) t << 1 | 1
using namespace std;

const int N = 65540*2;

class node{
public:
int l, r;
int cov;
int change; //表示该区间是否需要被改变;
void changeEdit(){ //按change进行操作
if(change) change = 0; //如果需要改变,当前区间标为不需要
else if(cov != -1) cov ^= 1; //如果当前段非单色, 对他进行^改变
else change = 1;
}
}node[N
*4];

int flag[N];

// 下分
void PushDown(int t){
if(node[t].cov != -1){
node[L(t)].cov
= node[R(t)].cov = node[t].cov;
node[L(t)].change
= node[R(t)].change = node[t].change;
}
if(node[t].change){
node[L(t)].changeEdit();
node[R(t)].changeEdit();
node[t].change
= 0;
}
}
//上传
void PushUp(int t){
if(node[L(t)].cov == node[R(t)].cov){
node[t].cov
= node[L(t)].cov;
}
else {
node[t].cov
= -1;
}
}

void creat(int t, int l, int r){
node[t].l
= l;
node[t].r
= r;
node[t].cov
= 0;
node[t].change
= 0;

if(l == r) return ;

int mid = (l + r) >> 1;

creat(L(t), l, mid);
creat(R(t), mid
+1, r);
}

void updata(int t, int l, int r, int v){
if(node[t].l > l || node[t].r < r) return ;

if(node[t].l >= l && node[t].r <= r){
//printf("%d %d %d\n", l, r, v);
node[t].cov = v;
node[t].change
= 0;
return ;
}

PushDown(t);
int mid = (node[t].l + node[t].r) >> 1;

if(l > mid)
updata(R(t), l, r, v);
else if(r <= mid)
updata(L(t), l, r, v);
else{
updata(L(t), l, mid, v);
updata(R(t), mid
+1, r, v);
}
PushUp(t);
}

void XOR(int t, int l, int r){
if(node[t].l > l || node[t].r < r) return ;

if(node[t].l == l && node[t].r == r){
//printf("%d %d %d\n", l, r, node[t].cov);
if(node[t].cov != -1)
node[t].cov
^= 1;
else
node[t].change
^= 1;
return ;
}

PushDown(t);
int mid = (node[t].l + node[t].r) >> 1;

if(l > mid)
XOR(R(t), l, r);
else if(r <= mid)
XOR(L(t), l, r);
else{
XOR(L(t), l, mid);
XOR(R(t), mid
+ 1, r);
}
PushUp(t);
}

void query(int t){
if(node[t].l == node[t].r){
flag[node[t].l]
= node[t].cov;
return ;
}
PushDown(t);
query(L(t));
query(R(t));
}

int main(){
//freopen("data.in", "r", stdin);

int l, r, i;
char s, p, q;

creat(
1, 0, N);

while(~scanf("%c %c%d,%d%c\n", &s, &p, &l, &r, &q)){
l
*= 2; r *= 2;
if(p == '(') l++;
if(q == ')') r--;

if(s == 'U'){
updata(
1, l, r, 1);
}
else if(s == 'I'){
if(l > 0)
updata(
1, 0, l - 1, 0);
if(r < N)
updata(
1, r + 1, N, 0);
}
else if(s == 'D'){
updata(
1, l, r, 0);
}
else if(s == 'C'){
if(l > 0)
updata(
1, 0, l - 1, 0);
if(r < N)
updata(
1, r + 1, N, 0);
XOR(
1, l, r);
}
else{
XOR(
1, l, r);
}
}
query(
1);
int begin, end, tmp = 1;
for(i = 0; i <= N; i++){
while(i <= N && !flag[i]) i++;
begin
= i;
if(i > N) break;

while(i <= N && flag[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");
putchar(
'\n');
return 0;
}
原文地址:https://www.cnblogs.com/vongang/p/2182900.html