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