poj3277(线段树+离散化+扫描线+测度)

一、.思路:有三种方法

1.插入时延迟更新(我自己的做法),效率还不错,应该是最大最小值的剪枝的作用吧,呵呵!

 

2.插入时精确覆盖,查询时向下记录最大值,一直查询到叶子结点


3.扫描线+测度

在线段树的结点里增加n,m,n表示线段数量,m表示这个区间的有效长度,由于使用了扫描线,因此每次计算的是一个局部的范围,简化了问题,插入矩形的左边时,对应区间的线段树加1,插入右边时就减1,因为扫描线是向右的,碰到左边,开始作用,碰到右边取消其作用!和poj1177做法是一样的,效率也还可以!

注意插入时对测度的修改,当该区间没有线段时应该递归的求解!然后查询就是O(1)的时间了。

二、代码

思路1的代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define min(i,j) (i<j?i:j)
#define max(i,j) (i>j?i:j)

typedef __int64 LL;
#define lson (root<<1)
#define rson (root<<1|1)
struct node
{
	int st,ed,c;
	int maxi,mini;
}ST[300000];
struct Line
{
	int x1,x2,h;
}line[40005];
int x[80005],tx[80005],n,num;
void build(int root,int st,int ed)
{
	ST[root].st=st;
	ST[root].ed=ed;
	ST[root].maxi=ST[root].mini=ST[root].c=0;
	
	if(ed>st+1)
	{
		build(lson,st,(st+ed)>>1);
		build(rson,(st+ed)>>1,ed);
	}
}

void insert(int root,int st,int ed,int c)
{
	if(c<=ST[root].mini)return;
	int l=ST[root].st,r=ST[root].ed;
	if(st<=l&&r<=ed)//l==r-1||
	{
		if(c>=ST[root].maxi)
		{
			ST[root].c=ST[root].maxi=ST[root].mini=c;
			return;
		}
	}
	
	if(ST[root].c>0)
	{
		ST[lson].c=ST[lson].maxi=ST[lson].mini=ST[root].c;
		ST[rson].c=ST[rson].maxi=ST[rson].mini=ST[root].c;
		ST[root].c=0;
	}
	 
	int mid=(l+r)>>1;
	if(st<mid)insert(lson,st,ed,c);
	if(ed>mid)insert(rson,st,ed,c);
	
	ST[root].mini=min(ST[lson].mini,ST[rson].mini);
	ST[root].maxi=max(ST[lson].maxi,ST[rson].maxi);
}
int Correspond(int t)
{
	int l=1,r=num;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(t>x[mid])
			l=mid+1;
		else r=mid;
	}
	return r;
}
__int64 sum(int root)
{
	int l=ST[root].st,r=ST[root].ed;
	if(ST[root].c>0)return (x[r]-x[l])*__int64(ST[root].c);
	if(l+1==r)return 0;//
	return sum(lson)+sum(rson);
}
int main()
{
#ifndef ONLINE_JUDGE
		//	freopen("data.in", "r", stdin);
		freopen("horizon.10.in", "r", stdin);
		freopen("data.out","w",stdout);
#endif
	
	int i;
	while(scanf("%d",&n)==1)
	{
		num=0;
		for(i=0;i<n;i++)
		{
			scanf("%d %d %d",&line[i].x1,&line[i].x2,&line[i].h);
			tx[num++]=line[i].x1,tx[num++]=line[i].x2;
		}
		sort(tx,tx+num);
		n<<=1;
		x[1]=tx[0];
		for(i=num=1;i<n;i++)
			if(tx[i]!=tx[i-1])
				x[++num]=tx[i];
			build(1,1,num);
			n>>=1;
			for(i=0;i<n;i++)
				insert(1,Correspond(line[i].x1),Correspond(line[i].x2),line[i].h);

			printf("%I64d\n",sum(1));

	}
	return 0;
}


思路2的代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define min(i,j) (i<j?i:j)
#define max(i,j) (i>j?i:j)

typedef __int64 LL;
#define lson (root<<1)
#define rson (root<<1|1)
#define N 40010
struct node
{
	int st,ed,c;
}ST[N*8];
struct Line
{
	int x1,x2,h;
}line[2*N];
int x[N*2],tx[N*2],n,num;
void build(int root,int st,int ed)
{
	ST[root].st=st;
	ST[root].ed=ed;
	ST[root].c=0;
	
	if(ed>st+1)
	{
		build(lson,st,(st+ed)>>1);
		build(rson,(st+ed)>>1,ed);
	}
}

void insert(int root,int st,int ed,int c)
{
	int l=ST[root].st,r=ST[root].ed;
	if(st<=l&&r<=ed)//l==r-1||
	{
		if(c>=ST[root].c)ST[root].c=c;
		return;//放在了if里面!
	}
	int mid=(l+r)>>1;
	if(st<mid)insert(lson,st,ed,c);
	if(ed>mid)insert(rson,st,ed,c);
}
int Correspond(int t)
{
	int l=1,r=num;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(t>x[mid])
			l=mid+1;
		else r=mid;
	}
	return r;
}
__int64 sum(int root,int maxi)
{
	maxi=maxi<ST[root].c?ST[root].c:maxi;
	int l=ST[root].st,r=ST[root].ed;
	if(l+1==r)return __int64(maxi)*(x[r]-x[l]);
	return sum(lson,maxi)+sum(rson,maxi);
}
int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in", "r", stdin);
	 freopen("horizon.9.in", "r", stdin);
#endif
	int i;
	while(scanf("%d",&n)==1)
	{
		num=0;
		for(i=0;i<n;i++)
		{
			scanf("%d %d %d",&line[i].x1,&line[i].x2,&line[i].h);
			tx[num++]=line[i].x1,tx[num++]=line[i].x2;
		}
		sort(tx,tx+num);
		n<<=1;
		x[1]=tx[0];
		for(i=num=1;i<n;i++)
			if(tx[i]!=tx[i-1])
				x[++num]=tx[i];
			build(1,1,num);
			n>>=1;
			for(i=0;i<n;i++)
				insert(1,Correspond(line[i].x1),Correspond(line[i].x2),line[i].h);
			
			printf("%I64d\n",sum(1,0));
			
	}
	return 0;
}


思路3的代码


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
using namespace std;

#define lson (rt<<1)
#define rson (lson|1)
#define LL __int64
#define N 400010

struct Seg
{
	int x,idx;
	bool left;
}segs[2*N];
int cnt;

bool cmp(const Seg & a,const Seg &b)
{
	return a.x<b.x;
}



struct Node
{
	int l,r,n;
	int m;
	void init(int ll,int rr)
	{
		l=ll,r=rr;
		n=m=0;
	}	
}tree[N*8];
int h[N],tot;

int find(int height)
{
	int l=0,r=tot-1,mid;
	while(l<r)
	{
		mid=(l+r)>>1;
		if(h[mid]<height)l=mid+1;
		else r=mid;
	}
	return l;
}

void build(int l,int r,int rt)
{
	tree[rt].init(l,r);
	if(l<r-1)
	{
		int mid=(l+r)>>1;
		build(l,mid,lson);
		build(mid,r,rson);
	}
}

int getM(int rt)
{
	if(tree[rt].m || tree[rt].l==tree[rt].r-1)return tree[rt].m;
	return tree[rt].m=getM(lson)+getM(rson);
}

void insert(int st,int ed,int rt,int num)
{
	int l=tree[rt].l,r=tree[rt].r;
	if(st<=l&&ed>=r)
	{
		tree[rt].n+=num;
		if(tree[rt].n==1)tree[rt].m=h[r]-h[l];
		else if(!tree[rt].n){tree[rt].m=0;getM(rt);}//叶子
		return;
	}
	
	int mid=(l+r)>>1;
	if(st<mid)insert(st,ed,lson,num);
	if(ed>mid)insert(st,ed,rson,num);
	
	if(!tree[rt].n)
	{
		tree[rt].m=0;
		getM(rt);
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("horizon.10.in", "r", stdin);
#endif
	int n;
	while(~scanf("%d",&n))
	{
		cnt=2*n;
		int i,l,r;
		for(i=0;i<n;i++)
		{
			l=i<<1,r=l|1;
			scanf("%d%d%d",&segs[l],&segs[r],h+i+1);
			segs[l].idx=segs[r].idx=h[i+1];
			segs[l].left=true;
			segs[r].left=false;
		}
		h[0]=0;
		sort(h+1,h+n+1);
		for(tot=i=1;i<n+1;i++)
		{
			if(h[i]==h[tot-1])continue;
			h[tot++]=h[i];
		}
		
		sort(segs,segs+cnt,cmp);
		
		for(i=0;i<cnt;i++)segs[i].idx=find(segs[i].idx);
		
		build(0,tot-1,1);//
		
		LL ans;
		for(ans=i=0;i<cnt;i++)
		{
			if(i)ans+=(segs[i].x-segs[i-1].x)*LL(tree[1].m);
			if(segs[i].left)insert(0,segs[i].idx,1,1);
			else insert(0,segs[i].idx,1,-1);
		}
		printf("%I64d\n",ans);
	}
	return 0;
}







你可能感兴趣的:(c,struct,tree,ini,Build,insert)