BZOJ 5168: [HAOI2014]贴海报 分块

5168: [HAOI2014]贴海报

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 89  Solved: 29
[Submit][Status][Discuss]

Description

Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委
员 会为选民准备了一个张贴海报的electoral墙。张贴规则如下:
1.electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子;
2.所有张贴的海报的高度必须与electoral墙的高度一致的;
3.每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报;
4.后贴的海报可以覆盖前面已贴的海报或部分海报。
现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。

Input

第一行: N M 分别表示electoral墙的长度和海报个数
接下来M行: Ai Bi 表示每张海报张贴的位置

Output

输出贴完所有海报后,在electoral墙上还可以看见的海报数。
1 0<= N <= 10000000 1<=M<=1000 1<= Ai <= Bi <=10000000
所有的数据都是整数。数据之间有一个空格

Sample Input

100 5
1 4
2 6
8 10
3 4
7 10

Sample Output

4


一眼线段树 之后发现开不下

m就1000 果断分块啊...

再有就是可以把端点离散化 再在每两个点中间插一个 之后每次暴力就好


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

typedef long long ll;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();}
	return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=10001000,M=1010;

int n,block;
int c[N],bel[N],col[10000];

inline void color(int l,int r,int x)
{
	register int i,tmp;
	if(bel[l]==bel[r])
	{
		tmp=col[bel[l]];
		if(l==(bel[l]-1)*block+1 && r==bel[l]*block)
		{col[bel[l]]=x;return ;}
		if(tmp)
		{
			col[bel[l]]=0;
			for(i=(bel[l]-1)*block+1;i<=min(bel[l]*block,n);++i) c[i]=tmp;
		}
		for(i=l;i<=r;++i) c[i]=x;
		return ;
	}
	
	for(i=bel[l]+1;i<=bel[r]-1;++i) col[i]=x;
	
	if(l==(bel[l]-1)*block+1)
		col[bel[l]]=x;
	else
	{
		if(col[bel[l]])
		{
			tmp=col[bel[l]];col[bel[l]]=0;
			for(i=(bel[l]-1)*block+1;i<l;++i) c[i]=tmp;
		}
		for(i=l;i<=min(bel[l]*block,n);++i) c[i]=x;
	}
	
	if(r==bel[r]*block)
		col[bel[r]]=x;
	else
	{
		if(col[bel[r]])
		{
			tmp=col[bel[r]];col[bel[r]]=0;
			for(i=r+1;i<=min(bel[r]*block,n);++i) c[i]=tmp;
		}
		for(i=(bel[r]-1)*block+1;i<=r;++i) c[i]=x;
	}
}

bool book[M];

int main()
{
	register int i,j,l,r;
	n=read();int m=read();
	block=ceil(sqrt(n));
	for(i=1,j=1;i<=n;++i,++j)
	{
		bel[i]=bel[i-1]+(j==1);
		if(j==block) j=0;
	}
	for(i=1;i<=m;++i)
	{
		l=read();r=read();
		color(l,r,i);
	}
	int ans(0);
	register int now(1);
	while(now<=n)
	{
		if(col[bel[now]])
		{
			if(!book[col[bel[now]]]) ans++;
			book[col[bel[now]]]=1;
			now=bel[now]*block+1;
			continue;
		}
		if(!book[c[now]] && c[now]) ans++;
		book[c[now]]=1;
		now++;
	}
	cout<<ans<<endl;
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值