HDU 5820 (可持久化线段树)

时间:2020-12-04 05:19:47

Problem Lights (HDU 5820)

题目大意

  在一个大小为50000*50000的矩形中,有n个路灯。(n<=500000)

  询问是否每一对路灯之间存在一条道路,使得长度为|x1 – x2| + |y1 – y2|且每个拐弯点都是路灯。

解题分析

  官方题解:

     HDU 5820 (可持久化线段树)

  除了从左往右扫描一遍外,个人认为还需从右往左扫描一遍,记录右上方的点的信息。 实际实现时,只需将整个图左右对称翻转一下即可。

  学习了一下可持久化线段树的正确姿势。

  可持久化线段树的空间一定要开大,开大,开大。

  下图为模拟的小数据可持久化线段树的构造。

HDU 5820 (可持久化线段树)

参考程序

 #include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std; #define N 1000008
#define M 50008
#define LL long long
#define lson l,m,rt<<1
#define rson m,r+1,rt<<1|1
#define clr(x,v) memset(x,v,sizeof(x)); const int mo = ;
const int inf = 0x3f3f3f3f;
const int INF = ;
/**************************************************************************/
struct node{
int x,y;
bool operator < (const node &b) const {
return x<b.x || x==b.x && y<b.y;
}
node(int x=,int y=):x(x),y(y){}
}a[N];
int n,flag;
map<pair<int,int>,int> Mpp; int mx[M],my[M]; int cnt;
int sum[N<<],ls[N<<],rs[N<<];
int root[M]; void dfs(int rt,int l,int r){
if (rt==) return;
printf("%d %d %d %d\n",rt,l,r,sum[rt]);
if (l==r) return;
int m=(l+r)/;
dfs(ls[rt],l,m);
dfs(rs[rt],m+,r);
}
void debug(){
printf("====================\n");
dfs(root[],,);
printf("\n");
dfs(root[],,);
printf("\n");
dfs(root[],,);
printf("\n");
dfs(root[],,);
printf("====================\n");
}
void pushup(int rt){
int l=ls[rt],r=rs[rt];
sum[rt]=sum[l]+sum[r];
}
void build(int &rt,int l,int r){
rt=++cnt;
sum[rt]=;
if (l==r) return;
int m=(l+r)/;
build(ls[rt],l,m);
build(rs[rt],m+,r);
pushup(rt);
}
void update(int pos,int val,int x,int &y,int l,int r){
y=++cnt;
if (l==r){
sum[y]=sum[x]+val;
return;
}
ls[y]=ls[x]; rs[y]=rs[x];
int m=(l+r)/;
if (pos <= m) update(pos,val,ls[x],ls[y],l,m);
if (m < pos) update(pos,val,rs[x],rs[y],m+,r);
pushup(y);
} int query(int L,int R,int rt,int l,int r){
if (L<=l && r<=R){
return sum[rt];
}
int m=(l+r)/;
int res=;
if (L <= m) res+=query(L,R,ls[rt],l,m);
if (m < R) res+=query(L,R,rs[rt],m+,r);
return res;
} void work1(){
clr(mx,); clr(my,);
cnt=;
build(root[],,);
int last=root[];
for (int i=;i<=n;i++){
int x1=a[i].x , y1=a[i].y;
int x2=a[my[y1]].x , y2=a[mx[x1]].y;
update(y1,,last,root[x1],,);
int k1=query(y2+,y1,root[x1],,);
int k2=query(y2+,y1,root[x2],,);
if (k1!=k2+) { flag=; return; }
mx[a[i].x]=i; my[a[i].y]=i; last=root[x1];
}
} int main(){
int T;
while (~scanf("%d",&n)){
if (n==) break;
Mpp.clear();
int num=;
for (int i=;i<=n;i++){
int x,y;
scanf("%d %d",&x,&y);
if (Mpp[make_pair(x,y)]==){
num++;
}
else
{
Mpp[make_pair(x,y)]=;
a[i-num].x=x;
a[i-num].y=y;
}
}
n=n-num;
sort(a+,a+n+);
flag=;
work1();
for (int i=;i<=n;i++) a[i].x=-a[i].x;
sort(a+,a+n+);
work1();
printf("%s\n",flag ? "YES" : "NO" );
}
}
/*
5
1 1
1 2
1 3
2 1
3 3
*/