Mayor's posters (线段树 离散化)

题目:http://poj.org/problem?id=2528

(哭了,什么都不会)
这道题要离散化(他们说),10000000很大,但是其实用不到那么多,N也就10000,答案最多也就那么点。
(怎么离散呢)
比如题目里的
1 4
2 6
8 10
3 4
7 10
先从小到大排序,然后去掉重复的,重新编号,最终上下一一对应
1 2 3 4 6 7 8 10
1 2 3 4 5 6 7 8

这样就省了嘛

#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson rt<<1,l,m//后来发现,宏定义真好用 
#define rson rt<<1|1,m+1,r
#define mem(n,m) memset(n,m,sizeof(n))
#define MAX 10000010  
using namespace std;
const int N=20010;
int lazy[N<<2];
int hash[MAX],record[N];//哭了,一直RE一直RE,因为我hash的数组开小了,哭了 
int c,n,le[N],ri[N];//区间左边、右边:left,right 
int ans;
int vis[20010];

void push_down(int rt) {
	if(lazy[rt]) {
		lazy[rt<<1|1] = lazy[rt<<1] = lazy[rt];
		lazy[rt] = 0;
	} 
}

void Updata(int L, int R, int x, int rt, int l, int r) { //更新
	if(L <= l && r <= R) {
		lazy[rt] = x;
		return;
	}	
	push_down(rt);
	int m = l+r >>1;
	if(L <= m) Updata(L, R, x, lson);
	if(R > m) Updata(L, R, x, rson);
}

void query(int rt, int l, int r) {
	if(lazy[rt]) {
		if(!vis[lazy[rt]]) {
			ans++;
			vis[lazy[rt]] = 1;
		}
		return ; 
	}
	int m = l+r >> 1;
	query(lson);
	query(rson);
}

int main() {
	scanf("%d",&c);
	while(c--) {
		ans=0;
		mem(vis,0);
		mem(hash,0);
		scanf("%d",&n);
		int k=0;
		for(int i=0;i<n;i++){
			scanf("%d%d",&le[i],&ri[i]);
			record[k++]=le[i];
			record[k++]=ri[i];
		}
		sort(record,record+k);
		int j=0;
		for(int i=0;i<k;i++) {//离散化 
			if(!hash[record[i]]) hash[record[i]]=++j;
		} 
		mem(lazy,0);
		for(int i=0;i<n;i++) {
			Updata(hash[le[i]],hash[ri[i]],i+1,1,1,j);
		}
		query(1,1,j);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43326028/article/details/86657273