zjnu 1779 KRUŽNICE(线段树成段更新+离散化)

本题题意:

给你n个圆,每个圆告诉你一个圆心和半径,圆心只能在x轴上,问你能把平面切割成几个部分,圆不可能相交。

思路就是把圆的左右区间先离散化一下, 判断一下区间是否被覆盖过,如果被覆盖过就+2,没有覆盖过就+1,最后算出的结果要加一。

AC代码:

/* ***********************************************
Author        :yzkAccepted
Created Time  :2016/3/28 19:35:45
TASK		  :ggfly.cpp
LANG          :C++
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
typedef __int64 ll;
const int maxn=300001;
const int INF=1<<27;
ll ans=0;
int n;
int tree[maxn<<4],col[maxn<<4];
#define lson l , m , rt << 1  
#define rson m + 1 , r , rt << 1 | 1  
struct node{
	ll lif,rig;
}p[maxn];
ll l[maxn<<1];
bool cmp(node a,node b)
{
	if(a.rig==b.rig) return a.lif>b.lif;
	return a.rig<b.rig;
}
void pushup(int rt)
{
	tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
}
void build(int l,int r, int rt)
{
	col[rt]=0;
	tree[rt]=0;
	if(l==r)
		return;
	int m=l+r>>1;
	build(lson);
	build(rson);
}
void pushdown(int rt)
{
	if(col[rt])
	{
		col[rt<<1]=col[rt<<1|1]=col[rt];
		tree[rt<<1]=1;
		tree[rt<<1|1]=1;
		col[rt]=0;
	}
}
void update(int L,int R,int l,int r,int rt) {  
    if (L <= l && r <= R) {  
        col[rt] = 1;  
        tree[rt] = 1;
        return ;  
    }  
    pushdown(rt );  
    int m = (l + r) >> 1;  
    if (L <= m) update(L , R , lson);  
    if (R > m) update(L , R  , rson);
	pushup(rt);	
}  
int query(int L,int R,int l,int r,int rt)
{
	if(tree[rt]==1)
		return 1;
	if(L<=l && r<=R)
	{	
		return tree[rt];}
	int m=(l+r)>>1;
	int ret=INF;
	if(L<=m)
		ret=min(ret,query(L,R,lson));
	if(R>m)
		ret=min(ret,query(L,R,rson));
	return ret;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
	int i,tot,j;
	ll x,r;
	scanf("%d",&n);
	tot=0;
	for(i=0;i<n;i++)
	{
		scanf("%I64d%I64d",&x,&r);
		p[i].lif=x-r;
		l[tot]=p[i].lif;
		tot++;
		p[i].rig=x+r;
		l[tot]=p[i].rig;
		tot++;
	}
	sort(l,l+tot);
	for(i=0;i<n;i++)
	{	
		p[i].lif=(lower_bound(l,l+tot,p[i].lif)-l+1)*2;
		p[i].rig=(lower_bound(l,l+tot,p[i].rig)-l+1)*2;
	}
	sort(p,p+n,cmp);
	build(1,n*4,1);
	for(i=0;i<n;i++)
	{
		if(query(p[i].lif,p[i].rig,1,n*4,1)==1)
		{	
			ans+=2;
		}
		else
		{
			ans++;
			update(p[i].lif,p[i].rig,1,4*n,1);
		}
	}
	printf("%I64d\n",ans+1);
	return 0;
}


你可能感兴趣的:(线段树)