线段树
\(O(nlogn)\)
本来是做过这道题的,原题是POJ2528 Mayor's posters
但是POJ上的数据有问题,导致我以为自己AC了。像这种区间的题尤其要注意离散化时要离散化左右边界
举个洛谷上的例子
当出现这种情况[5,7],[1,5],[7,8]按顺序覆盖的话,就会出问题: 离散化为区间[2,3],[1,2],[3,4]那么按这样覆盖就会把第一张海报覆盖掉,但实际上第一张海报没有完全被覆盖 那该怎么办?solution:在每个离散区间中强行加一个点比如说在[1,5]加上2,[5,7]加上6,[7,8]由于是相邻的所以不要加 这样问题就解决了
回顾这道题,因为是区间修改,所以可以用线段树。查询答案时既可以递归到叶子节点再返回,也可以遇到一个有颜色的区间便返回。在维护上传标记时,若左右儿子颜色相同才上传,否则不上传
这是修改后的代码
#include<bits/stdc++.h> using namespace std; #define go(i,a,b) for(int i=(a);i<=(b);++(i)) #define com(i,a,b) for(int i=(a);i>=(b);--(i)) #define mem(a,b) memset((a),(b),sizeof(a)) #define inf 0x3f3f3f3f #define fin freopen("input.txt","r",stdin) #define fout freopen("output.txt","w",stdout) typedef long long ll; const int maxn=10008; struct tree{ int l,r,co; #define l(x) t[x].l #define r(x) t[x].r #define co(x) t[x].co #define lson rt<<1 #define rson rt<<1|1 }t[maxn*8]; int n,m,ans,sad[maxn*2],rk[maxn*2],tot=0,l[maxn],r[maxn],vis[maxn]; bool flag[maxn]; void read(int &x){ int f=1;char s=getchar();x=0; while(!isdigit(s)){if(s=='-') f=-1;s=getchar();} while(isdigit(s)){x=(x<<3)+(x<<1)+s-'0';s=getchar();} x*=f; } void build(int rt,int l,int r){ l(rt)=l,r(rt)=r; if(l==r){ return; } int mid=l+r>>1; build(lson,l,mid); build(rson,mid+1,r); } void push_up(int rt){ if(co(lson)==co(rson)) co(rt)=co(lson); else co(rt)=-1; } void push_down(int rt){ if(co(rt)!=-1&&co(rt)!=0){ co(lson)=co(rt); co(rson)=co(rt); co(rt)=0; } } void update(int rt,int x,int y,int val){ if(l(rt)>=x&&r(rt)<=y){ co(rt)=val; return; } push_down(rt); int mid=l(rt)+r(rt)>>1; if(x<=mid) update(lson,x,y,val); if(y>mid) update(rson,x,y,val); push_up(rt); } void get_ans(int rt){ if(co(rt)>0){ flag[co(rt)]=1; return; } if(l(rt)==r(rt)) return; get_ans(lson),get_ans(rson); } int main(){ //fin; int T;read(T); while(T--){ mem(flag,0); read(m); ans=tot=0; mem(vis,0); go(i,1,m){ read(l[i]),read(r[i]); sad[++tot]=l[i],rk[tot]=l[i]; sad[++tot]=r[i],rk[tot]=r[i]; sad[++tot]=l[i]+1,rk[tot]=l[i]+1; sad[++tot]=r[i]+1,rk[tot]=r[i]+1; sad[++tot]=l[i]-1,rk[tot]=l[i]-1; sad[++tot]=r[i]-1,rk[tot]=r[i]-1; } sort(sad+1,sad+tot+1); tot=unique(sad+1,sad+tot+1)-sad-1; go(i,1,m){ l[i]=lower_bound(sad+1,sad+tot+1,l[i])-sad; r[i]=lower_bound(sad+1,sad+tot+1,r[i])-sad; int f=1; } build(1,1,tot); go(i,1,m){ update(1,l[i],r[i],i); } get_ans(1); go(i,1,m) ans+=flag[i]; printf("%d\n",ans); } return 0; }