ACM-ICPC 2018 徐州赛区网络预赛 G 题 Trace

There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( x , y ) means the wave is a rectangle whose vertexes are ( 0 , 0 ), ( x , 0 ), ( 0 , y ), ( x , y ). Every time the wave will wash out the trace of former wave in its range and remain its own trace of ( x , 0 ) -> ( x , y ) and ( 0 , y ) -> ( x , y ). Now the toad on the coast wants to know the total length of trace on the coast after n waves. It's guaranteed that a wave will not cover the other completely.

Input

The first line is the number of waves n(n≤50000).

The next n lines,each contains two numbers x y ,( 0<x , y≤10000000 ),the i-th line means the i-th second there comes a wave of ( x , y ), it's guaranteed that when 1≤i , j≤n,xi≤xj and yi​≤yj​ don't set up at the same time.

Output

An Integer stands for the answer.

Hint:

As for the sample input, the answer is 3+3+1+1+1+1=10

样例输入

3
1 4
4 1
3 3

样例输出

10

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

题解:

以横坐标x建立线段树(记得点要离散化),维护区间最大最小的y值,然后按点倒序来加入。

然后同样的再以纵坐标y建立线段是维护区间最大最小的x值,其他同上。

代码:

/*G*/
#include <cstdio>
#include <algorithm>
#include <cstring>
 
using namespace std;
 
const int MAXN = 50005;
 
int lx,ly;
int board[MAXN][2]; 
int bix[MAXN];
int biy[MAXN];
 
struct Tr{
	int len,ma,mi;
	long long num;
}Tree[4*MAXN];
 
void Build(int temp,int left,int right,bool flag){
	Tree[temp].mi = Tree[temp].ma = Tree[temp].num = 0; 
	if(left == right){
		if(flag)Tree[temp].len = bix[left]-bix[left-1];
		else Tree[temp].len = biy[left]-biy[left-1];
		return ;
	}
	int mid = left + (right-left)/2;
	Build(temp<<1,left,mid,flag);
	Build(temp<<1|1,mid+1,right,flag);
	Tree[temp].len = Tree[temp<<1].len + Tree[temp<<1|1].len;
}
 
int add[4*MAXN];
 
void Pushdown(int temp,int left,int right){
	add[temp<<1] += add[temp];
	add[temp<<1|1] += add[temp];
	int mid = left + (right-left)/2;
	Tree[temp<<1].num += add[temp]*Tree[temp<<1].len;
	Tree[temp<<1|1].num += add[temp]*Tree[temp<<1|1].len;
	Tree[temp<<1].ma = Tree[temp<<1|1].ma = Tree[temp].ma;
	Tree[temp<<1].mi = Tree[temp<<1|1].mi = Tree[temp].mi;
	add[temp] = 0;
}
 
void Updata(int temp,int left,int right,int ql,int qr,int value){ 
	if(ql>right || qr<left)return;
	if(ql<=left && qr>=right){
		if(Tree[temp].ma < value){
			Tree[temp].ma = Tree[temp].mi = value;
			add[temp] += 1;
			Tree[temp].num += Tree[temp].len;
			return;
		}
		else if(Tree[temp].mi >= value)return;
	}
	if(add[temp])Pushdown(temp,left,right);
	int mid = left + (right-left)/2;
	if(ql<=mid)Updata(temp<<1,left,mid,ql,qr,value);
	if(qr>mid)Updata(temp<<1|1,mid+1,right,ql,qr,value);
	Tree[temp].ma = max(Tree[temp<<1].ma,Tree[temp<<1|1].ma);
	Tree[temp].mi = min(Tree[temp<<1].mi,Tree[temp<<1|1].mi);
	Tree[temp].num = Tree[temp<<1].num + Tree[temp<<1|1].num;
}
 
int BiX(int x){
	int l=1,r=lx;
	while(l<=r){
		int m = l + (r-l)/2;
		if(bix[m] == x)return m;
		else if(bix[m] > x)r = m-1;
		else l = m+1;
	}
	return -1;
}
 
int BiY(int y){
	int l=1,r=ly;
	while(l<=r){
		int m = l + (r-l)/2;
		if(biy[m] == y)return m;
		else if(biy[m] > y)r = m-1;
		else l = m+1;
	}
	return -1;
}
 
int main(){
	
	int N;
	while(scanf("%d",&N) == 1){
		int mx = 0,my = 0;
		long long sum = 0;
		for(int i=1 ; i<=N ; ++i){
			scanf("%d %d",&board[i][0],&board[i][1]);
			bix[i] = board[i][0];
			biy[i] = board[i][1];
		}
		bix[0] = biy[0] = 0;
		
		sort(bix+1,bix+1+N);
		lx = unique(bix+1,bix+1+N)-(bix+1);
		sort(biy+1,biy+1+N);
		ly = unique(biy+1,biy+1+N)-(biy+1);
		
		memset(add,0,sizeof add);
		Build(1,1,lx,true);
		for(int i=N ; i>=1 ; --i){
			int bi = BiX(board[i][0]);
			Updata(1,1,lx,1,bi,board[i][1]);
		}
		sum += Tree[1].num;
		
		memset(add,0,sizeof add);
		Build(1,1,ly,false);
		for(int i=N ; i>=1 ; --i){
			int bi = BiY(board[i][1]);
			Updata(1,1,ly,1,bi,board[i][0]);
		}
		sum += Tree[1].num;
		printf("%lld\n",sum);
	}
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值