首页 > 其他分享 >poj 2528 Mayor's posters 线段树+离散化

poj 2528 Mayor's posters 线段树+离散化

时间:2023-09-15 10:37:48浏览次数:47  
标签:struct int colour tree 2528 mid poj posters id


离散化处理要注意+1(看了HH大牛的博客懂的,以前自己的代码是不对的)

例如数据:

1

3
1 10
1 3
6 10
这样,普通离散化处理  {1 3 6 10}, 然后此程序会操作成点染色,于是结果为2, 但正确答案为 3;
HH大牛给出一种离散化方法:
      如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了 (详见下面代码)按照上述方法离散化处理,为 {1 3 4 6 7 10 11 },  染色, 结果为 3;这样,就很简洁地将一个数字表示成一段区域。

#include<cstdio>
#include<cstdlib>
#include<cstring>
int seq[10010][2],ans;
bool visit[10010];

struct Line{
	int begin;
	int num;//表示其为第几张海报的首尾,首位负,尾为正
}line[20010];

struct Tree{
	int s;
	int t;
	int c;
}tree[140010];

int cmp(const void * a,const void *b){
	struct Line *aa=(struct Line *)	a;
	struct Line *bb=(struct Line *)	b;
	return aa->begin-bb->begin;
}

void build(int s,int t,int id){
	tree[id].s=s;
	tree[id].t=t;
	tree[id].c=0;
	if(s!=t){
		int mid=(tree[id].s+tree[id].t)>>1;
		build(s,mid,id*2);
		build(mid+1,t,id*2+1);
	}
}

void insert(int s,int t,int id,int colour){
	if(tree[id].s==s && tree[id].t==t){
		tree[id].c=colour;
		return ;
	}//否则的话从s到t的线段一定在tree[id]所表示的线段之内
	if(colour==tree[id].c)
		return ;

	if(tree[id].c>0){
		tree[id*2].c=tree[id].c;
		tree[id*2+1].c=tree[id].c;
	}
	int mid=(tree[id].s+tree[id].t)>>1;
	if(mid<s)
		insert(s,t,id*2+1,colour);
	else if(mid>=t)
		insert(s,t,id*2,colour);
	else{
		insert(s,mid,id*2,colour);
		insert(mid+1,t,id*2+1,colour);
	}
	if(tree[id*2+1].c!=tree[id*2].c || !tree[id*2+1].c || !tree[id*2].c)
		tree[id].c=0;
}

void search(int id){
	if(tree[id].c!=0){
		if(visit[tree[id].c]==false){
			ans++;
			visit[tree[id].c]=true;
		}
		return;
	}
	if(tree[id].s!=tree[id].t){
		search(id*2);
		search(id*2+1);
	}
}

int main(){
	int n,i,t,T;
	scanf("%d",&T);
	for(t=1;t<=T;t++){
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d %d",&seq[i][0],&seq[i][1]);
			line[2*i-1].begin=seq[i][0];
			line[2*i-1].num=-i;
			line[2*i].begin=seq[i][1];
			line[2*i].num=i;
		}
		qsort(&line[1],2*n,sizeof(line[1]),cmp);

		int temp=line[1].begin,tp=1;  //这里去掉了重复的line
		for(i=1;i<=2*n;i++){
			if(line[i].begin!=temp){
				tp++;
				if(line[i].begin>temp+1)
					tp++;         //这个+1操作很重要
				temp=line[i].begin;
			}
			if(line[i].num<0)
				seq[-line[i].num][0]=tp;
			else
				seq[line[i].num][1]=tp;
		}//离散化

		build(1,tp,1);

		for(i=1;i<=n;i++){
			insert(seq[i][0],seq[i][1],1,i);
		}

		ans=0;
		memset(visit,false,sizeof(visit));
		search(1);
		printf("%d\n",ans);
	}
}

 

 

标签:struct,int,colour,tree,2528,mid,poj,posters,id
From: https://blog.51cto.com/u_16263395/7477988

相关文章

  • POJ 2823 Sliding Window 单调队列
    这道题就是用单调队列来维护,但是用G++交TLE,用c++5000多ms,真是囧...代码很丑,就凑合着看吧#include<stdio.h>inta[1000009],que[1000009];intmain(){ intn,k,i,head,tail,flag=1,f; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) scanf("%d",&a[i]); head=......
  • POJ 2057 The Lost House 树形DP+贪心
          最近一直在做树形dp,感觉这道题出的非常不错。卡了我一天。。      一上来读完题感觉和dp的思路很像,但是自己太弱了,无从下手。于是各种百度看结题报告、看论文。推荐几个结题报告 http://blog.sina.com.cn/s/blog_5f5353cc0100hd08.html还有06年国家集训队杨......
  • poj 1182 食物链---带权值的并查集
    这题就一组数据,用while(scnaf(“%d%d”,&n,&m)!=EOF)..就wa了,我wa了数次,无语了。。带权值的并查集,d[]数组存的是每个点和根节点的关系,同类为d[i]=0; 根节点吃i点为d[i]=1; i点吃根节点为d[i]=2;自己画图感受一下吧!!#include<stdio.h>#include<string.h>#include<stdlib.h>in......
  • POJ 2186-Popular Cows ---强连通分量
    本题让求有多少点 是图中所有点都可到达改点的定理:在一个有向图中,如果有一个节点的出度为0,并且仅有一个这样的点,则该图中所有的点都可到达该点先求出图的强连通分量,然后将每个强连通分量化为一个层次,求是否存在一个强连通分量,该分量的出度为一,并且仅有一个这样的分量,则该连通分量......
  • POJ 2299 Ultra-QuickSort ---归并排序 求逆序
    归并排序的模板。能求逆序。。。。#include<stdio.h>#include<string.h>intn;longlonga[500005],b[500005];longlongsum;voidmerge(intl,intm,intr){ inti=l,j=m+1,k=0; while(i<=m&&j<=r) { if(a[i]<=a[j]) b[k++]=a[i++]; else......
  • poj 4604 Deque-----2013多校联合赛第一场--1005
    做了一天,终于做出来了。。结题报告:考虑题目的一个简化版本:使双端队列单调上升。对于序列A和队列Q,找到队列中最早出现的数字Ax,则Ax将Q分成的两个部分分别是原序列中以Ax开始的最长上升和最长下降序列,答案即为这两者之和的最大值。而对于本题,由于存在相同元素,所以只要找到以Ax......
  • poj 4607 Park Visit --2013多校联合赛第一场---1008
    解题报告:首先如果k小于等于直径长度,那么答案为k−1。如果k大于直径长度,设直径长度为r,那么答案为r−1+(k−r)∗2。 先找树的最长路;找树中任意一点,dfs找该点所能达到的最远的点vv,然后从vv点dfs找树的最长路。。#include<stdio.h>#include<string.h>#include<vector>#includ......
  • poj 1469 COURSES----二分图
    二分图的最大匹配,模板。。#include<stdio.h>#include<string.h>booledge[110][310],visited[310];intcx[110],cy[310];intn,m;intpath(intu){ intv; for(intv=1;v<=m;v++) if(edge[u][v]&&!visited[v]){ visited[v]=1; if(cy[v]==-1||......
  • poj 1325 Machine Schedule---二分图求最小顶点覆盖
    二分图求最小顶点覆盖。。注意本题说,机器开始在0开始,所以就是默认和0相连的job已经被完成了,所以我是从1开始扫的点正常的话,要将edge【】【】和0相连的边值赋为0,表示该job已经被完成。。。#include<stdio.h>#include<string.h>booledge[110][110],visited[110];intcx[110],cy......
  • POJ 2253 Frogger
    //变形的dijkstra//核心代码//if(d[j]>max(d[k],map[k][j]))//d[j]=max(d[k],map[k][j]);#include<stdio.h>#include<string.h>#include<math.h>#include<cmath>usingnamespacestd;#definemax999999structnode{ intx,y;}p[210];intmap......