原题链接
考察:线段树
线段树染色问题
思路:
每次张贴海报都是一次区间修改.而染色区间l,r范围过大.需要离散化.离散化后就可以定义线段树了.
struct Node{ int l,r,c;//l,r左右端点.c为该区间的颜色,同时也是懒标记 }tr[N<<3];
这里定义c为该区间颜色种类是不可取的,无法用子节点更新父节点信息.定义
void push_up(int u) { if(tr[u<<1].c==tr[u<<1|1].c) tr[u].c = tr[u<<1].c; else tr[u].c = -1; }
然后比较关键的是Push_down.很直观的感受就是当父节点是-1时,不能简单地push_down.注意这点就可以了.
最后的一个关键点是,本来不相邻的区间,离散化后会变成相邻的.此时计数可能会少一个.eg:
1 3 1 10 1 4 6 10
离散化后为:
1 4
1 2
3 4
合并会记录两个.实际上有3个.这时需要再4与6之间插入一个数,使其为不相邻.
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> using namespace std; const int N = 100010; int n; vector<int> v; bool st[N]; struct Node{ int l,r,c; }tr[N<<3]; struct Segment{ int l,r,op; }seg[N]; int get(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1; } void push_up(int u) { if(tr[u<<1].c==tr[u<<1|1].c) tr[u].c = tr[u<<1].c; else tr[u].c = -1; } void build(int u,int l,int r) { tr[u].l = l,tr[u].r = r; if(l==r) return; int mid = l+r>>1; build(u<<1,l,mid),build(u<<1|1,mid+1,r); } void push_down(int u) { if(tr[u].c!=-1) tr[u<<1].c = tr[u<<1|1].c = tr[u].c; tr[u].c = 0; } void modify(int u,int l,int r,int x) { if(tr[u].l>=l&&tr[u].r<=r) { tr[u].c = x; return; } push_down(u); int mid = tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,x); if(mid<r) modify(u<<1|1,l,r,x); push_up(u); } void query(int u,int l,int r) { if(tr[u].l>=l&&tr[u].r<=r&&tr[u].c!=-1) { st[tr[u].c] = 1; return; } // push_down(u); int mid = tr[u].l+tr[u].r>>1; if(l<=mid) query(u<<1,l,r); if(mid<r) query(u<<1|1,l,r); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); v.clear(); memset(tr,0,sizeof tr); for(int i=1;i<=n;i++) { int l,r; scanf("%d%d",&l,&r); seg[i].l = l,seg[i].r = r,seg[i].op = i; v.push_back(l),v.push_back(r); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); int sz = v.size()-1; for(int i=0;i<sz;i++) { int a = v[i],b = i+1>=v.size()?a:v[i+1]; if(b-a>1) v.push_back(a+1); } sort(v.begin(),v.end()); build(1,1,v.size()); for(int i=1;i<=n;i++) { int l = get(seg[i].l),r = get(seg[i].r); modify(1,l,r,seg[i].op); } query(1,1,v.size()); int ans = 0; for(int i=1;i<=n;i++) ans+=st[i],st[i] = 0; printf("%d\n",ans); } return 0; }