其实就是线段树的一个水题,不过好久没写,加之第一次写离散化,出现各种细节错误,调到蛋碎。。。。。。QAQ
/****************************** * author :crazy_石头 * data structure: 线段树+离散化 * created time:2013/11/3 21:32 * Pro:POJ 2528 * Judge Status:Accepted * Memory:1200K * Time:79MS *******************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define rep(i,h,n) for(int i=(h);i<(n);i++) #define C system("pause") const int maxn=20000+5; int res; struct Tree { int l,r,color;//记录结点左右儿子及颜色; }T[maxn<<2]; struct Line { int id,num;//记录端点坐标及当前贴到的海报的编号,就是当前贴到第几张海报; }line[maxn<<1]; int segment[maxn][2];//记录输入两个端点坐标值; bool vis[maxn]; inline void fuck() { puts("FUCK!"); } inline bool cmp(Line A,Line B) { return A.id<B.id; } inline void pushdown(int rt,int color)//从顶向下传递,把lazy标记从父节点传到子节点,并取消父节点的标记; { if(T[rt].color>0&&T[rt].color!=color) { T[rt<<1].color=T[rt<<1|1].color=T[rt].color; T[rt].color=0; } } inline void build(int l,int r,int rt) { T[rt].l=l; T[rt].r=r; T[rt].color=0;//开始都未标记,颜色都为0; if(l==r) return ; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } inline void update(int l,int r,int rt,int color) { if(T[rt].l==l&&T[rt].r==r) { T[rt].color=color; return ; } pushdown(rt,color); int mid=(T[rt].l+T[rt].r)>>1; if(r<=mid)//当前查询区间的右端小于mid则说明在左子树; update(l,r,rt<<1,color); else if(l>mid)//右子树; update(l,r,rt<<1|1,color); else //都有; { update(l,mid,rt<<1,color); update(mid+1,r,rt<<1|1,color); } } inline void dfs(int rt) { if(T[rt].color) { if(!vis[T[rt].color]) { res++; vis[T[rt].color]=1; } return; } dfs(rt<<1); dfs(rt<<1|1); } int main() { int test,n; while(~scanf("%d",&test)) { while(test--) { scanf("%d",&n); rep(i,0,n) { scanf("%d%d",&segment[i][0],&segment[i][1]); line[i<<1].id=segment[i][0]; line[i<<1].num=-(i+1);//负数表示线段起点; line[i<<1|1].id=segment[i][1]; line[i<<1|1].num=i+1; } sort(line,line+2*n,cmp);//所有端点升序排列; int tmp=line[0].id; int cnt=1; rep(i,0,2*n)//准备进行离散化; { if(tmp!=line[i].id) { cnt++; tmp=line[i].id; } if(line[i].num<0) segment[-line[i].num-1][0]=cnt; else segment[line[i].num-1][1]=cnt; }//完成离散化过程; build(1,cnt,1); rep(i,0,n)//对离散化(相当于哈希映射的过程,其实可以用map更方便点)后的数字进行更新操作; update(segment[i][0],segment[i][1],1,i+1); memset(vis,0,sizeof(vis)); res=0; dfs(1); printf("%d\n",res); } } return 0; } |
* This source code was highlighted by YcdoiT. ( style: Colorful )