第七届浙江省赛C题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3749
比赛的时候还是很容易就想到了“线段树+离散化”,说明之前一些线段树的题目做了还是有效果的。但是接下来就是悲剧的时刻,没有想清楚怎么离散化,还有就是更新的函数,构造不出来,知道“线段树+离散化”又有什么用呢?唉,对线段树理解地不够深刻的。。。由于比赛中这道题目的AC率不高,我们队还有一些很多人通过的题没有AC,我就立马放弃了这道题,想最后还有时间的话,再来想想。 跟预想的一样,比赛的时候是没有时间再看这道题了。 比赛结束之后,看到了解题报告,后来又参看了http://boskijr.is-programmer.com/posts/17295.html#more Boski Jr.的代码,然后终于AC了。 学到了一招比较好的离散化的方式,使用半开半必的区间,比如 [ a , b ] 可以用 [ a, b+1 ) 来代替,可以省下不少空间呢。 以下是我的代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
  {
int s,t;
char op[3];
};
struct segment
  {
int l,r;
int left,right; // 记录区间两端的高度
int flag; // 记录整段区间被下压的次数
int count; // 记录区间中处于高度0的条数
};

const int maxn = 21000;
node a[maxn];
segment tree[maxn<<3];
int lisan[maxn<<1];

void make_tree( int v, int l, int r )
  {
int mid;
tree[v].l = l, tree[v].r = r;
tree[v].flag = tree[v].left = tree[v].right = 0;
tree[v].count = 1;
if( l + 1 != r )
 {
mid = ( l + r ) >> 1;
make_tree( v<<1, l, mid );
make_tree( ( v<<1 ) + 1, mid, r );
}
}

void update( int v, int s, int t, int c )
  {
int mid;
if( lisan[tree[v].l] == s && lisan[tree[v].r] == t )
 {
tree[v].flag += c;
tree[v].left += c;
tree[v].right += c;
if( tree[v].flag ) // 如果区间高度不是0,说明被下压,没有0线段
tree[v].count = 0;
else // 叶子节点
if( tree[v].l + 1 == tree[v].r )
tree[v].count = 1;
else // 一般节点
tree[v].count = tree[v<<1].count + tree[(v<<1)+1].count -
( tree[v<<1].right == 0 && tree[(v<<1)+1].left == 0 );
return ;
}
mid = ( tree[v].l + tree[v].r ) >> 1;
if( lisan[mid] >= t ) update( v<<1, s, t, c );
else if( lisan[mid] <= s ) update( (v<<1)+1, s, t, c );
else
 {
update( v<<1, s, lisan[mid], c );
update( (v<<1)+1, lisan[mid], t, c );
}
tree[v].left = tree[v<<1].left + tree[v].flag;
tree[v].right = tree[(v<<1)+1].right + tree[v].flag;

if( tree[v].flag ) tree[v].count = 0;
else
tree[v].count = tree[v<<1].count + tree[(v<<1)+1].count -
( tree[v<<1].right == 0 && tree[(v<<1)+1].left == 0 );
}

void init( int n, int m )
  {
int i,len=0;
lisan[len++] = 0;
lisan[len++] = n;
for( i = 0; i < m; i++ )
 {
scanf("%s%d%d",a[i].op,&a[i].s,&a[i].t);
a[i].t++;
lisan[len++] = a[i].s;
lisan[len++] = a[i].t;
}
sort( lisan, lisan + len );
len = unique( lisan, lisan + len ) - lisan;
make_tree( 1, 0, len-1 );
}

int main( )
  {
int i,t,n,m,k = 1;
scanf("%d",&t);
while( t-- )
 {
scanf("%d%d",&n,&m);
init( n, m );
printf("Case #%d:\n",k++);
for( i = 0; i < m; i++ )
 {
update( 1, a[i].s, a[i].t, ( a[i].op[0] == 'p' ? 1 : -1 ) );
printf("%d\n",tree[1].count);
}
}
return 0;
}

|