[HAOI2014]贴海报

  这道题我也是用线段树做的,也是区间覆盖。

  比较好想首先读入所有输入,倒序处理,对于一张海报,查询其对应区间有没有被完全覆盖,完全覆盖表示后面贴的那些海报会将这张海报完全盖住,否则的话,这张海报就会被看到,并且将其所对应的区间在线段树上进行覆盖操作。

  n比较大达到了1e7,按理说线段树应该过不了,但是过了......

  正解浮水法?

  现在我真的学不进去新算法了,甚至题也不想做,所以我一直在补题解。

 

// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<ctime>
using namespace std;
const int M=1000+10,N=(int)1e7+10;
int n,m,x[M],y[M],ans;
struct Node {
	int lc,rc; bool cover;
	Node():lc(0),rc(0),cover(0) {}
};
struct SegmentTree {
	int root,cnt; Node nd[N<<1];
	SegmentTree():root(0),cnt(0) {}
	void build(int &o,int l,int r) {
		if(!o) o=++cnt;
		if(l==r) return ;
		int mid=(l+r)>>1;
		build(nd[o].lc,l,mid);
		build(nd[o].rc,mid+1,r);
	}
	bool Cover(int o,int L,int R,int l,int r) {
		Node &p=nd[o];
		if(p.cover) return true;
		if(l<=L&&R<=r) {
			p.cover=true;
			return false;
		}
		else {
			int mid=(L+R)>>1;
			bool f1=false,f2=false;
			if(l<=mid) f1=Cover(p.lc,L,mid,l,r);
			if(r>mid) f2=Cover(p.rc,mid+1,R,l,r);
			p.cover=nd[nd[o].lc].cover&nd[nd[o].rc].cover;
			if(l<=mid&&r>mid) return f1&f2;
			if(l<=mid) return f1;
			return f2;
		}
	}
}t;
int main() {
	freopen("ha14d.in","r",stdin);
	freopen("ha14d.out","w",stdout);
	//clock_t start,end;
	//start=clock();
	scanf("%d%d",&n,&m);
	t.build(t.root,1,n);
	for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]);
	for(int i=m;i>=1;i--) 
		if(!t.Cover(t.root,1,n,x[i],y[i]))
			++ans;
	printf("%d\n",ans);
	//end=clock();
	//printf("%.3lf\n",(double)(end-start)/CLOCKS_PER_SEC);
	//printf("%d\n",sizeof(t.nd));
	return 0;
}

 

posted @ 2018-04-15 19:54  qjs12  阅读(111)  评论(0编辑  收藏  举报