HDU 5820 (可持久化线段树)

Problem Lights (HDU 5820)

题目大意

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

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

解题分析

  官方题解:

     

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

 

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

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

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

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17 
 18 #define N 1000008             
 19 #define M 50008    
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m,r+1,rt<<1|1 
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 
 25 const int mo  = 1000000007;
 26 const int inf = 0x3f3f3f3f;
 27 const int INF = 2000000000;
 28 /**************************************************************************/ 
 29 struct node{
 30     int x,y;
 31     bool operator < (const node &b) const {
 32         return x<b.x || x==b.x && y<b.y;
 33     }
 34     node(int x=0,int y=0):x(x),y(y){}
 35 }a[N];
 36 int n,flag;
 37 map<pair<int,int>,int> Mpp;
 38 
 39 int mx[M],my[M];
 40 
 41 int cnt;
 42 int sum[N<<3],ls[N<<3],rs[N<<3];
 43 int root[M];
 44 
 45 void dfs(int rt,int l,int r){
 46     if (rt==0) return;
 47     printf("%d %d %d %d\n",rt,l,r,sum[rt]);
 48     if (l==r) return;
 49     int m=(l+r)/2;
 50     dfs(ls[rt],l,m);
 51     dfs(rs[rt],m+1,r);
 52 }
 53 void debug(){
 54     printf("====================\n");
 55     dfs(root[0],1,3);
 56     printf("\n");
 57     dfs(root[1],1,3);
 58     printf("\n");
 59     dfs(root[2],1,3);
 60     printf("\n");
 61     dfs(root[3],1,3);
 62     printf("====================\n");
 63 }
 64 void pushup(int rt){
 65     int l=ls[rt],r=rs[rt];
 66     sum[rt]=sum[l]+sum[r];
 67 }
 68 void build(int &rt,int l,int r){
 69     rt=++cnt;
 70     sum[rt]=0;
 71     if (l==r) return;
 72     int m=(l+r)/2;
 73     build(ls[rt],l,m);
 74     build(rs[rt],m+1,r);
 75     pushup(rt);
 76 }
 77 void update(int pos,int val,int x,int &y,int l,int r){
 78     y=++cnt;
 79     if (l==r){
 80         sum[y]=sum[x]+val;
 81         return;
 82     }
 83     ls[y]=ls[x]; rs[y]=rs[x];
 84     int m=(l+r)/2;
 85     if (pos <= m) update(pos,val,ls[x],ls[y],l,m);
 86     if (m  < pos) update(pos,val,rs[x],rs[y],m+1,r);
 87     pushup(y);
 88 }
 89 
 90 int query(int L,int R,int rt,int l,int r){
 91     if (L<=l && r<=R){
 92         return sum[rt];
 93     }
 94     int m=(l+r)/2;
 95     int res=0;
 96     if (L <= m) res+=query(L,R,ls[rt],l,m); 
 97     if (m <  R) res+=query(L,R,rs[rt],m+1,r);
 98     return res; 
 99 }
100 
101 void work1(){
102     clr(mx,0); clr(my,0);
103     cnt=0;         
104     build(root[0],1,50000);
105     int last=root[0];
106     for (int i=1;i<=n;i++){
107         int x1=a[i].x , y1=a[i].y;
108         int x2=a[my[y1]].x , y2=a[mx[x1]].y;
109         update(y1,1,last,root[x1],1,50000);
110         int k1=query(y2+1,y1,root[x1],1,50000);
111         int k2=query(y2+1,y1,root[x2],1,50000);
112         if (k1!=k2+1) { flag=0; return; }
113         mx[a[i].x]=i; my[a[i].y]=i; last=root[x1]; 
114     }
115 }
116 
117 int main(){
118     int T;
119     while (~scanf("%d",&n)){
120         if (n==0) break;
121          Mpp.clear();
122         int num=0;
123         for (int i=1;i<=n;i++){
124             int x,y;
125             scanf("%d %d",&x,&y);
126             if (Mpp[make_pair(x,y)]==1){
127                 num++;
128             } 
129             else
130             {
131                 Mpp[make_pair(x,y)]=1;
132                 a[i-num].x=x;
133                 a[i-num].y=y;
134             }
135         }
136         n=n-num;
137         sort(a+1,a+n+1);
138         flag=1;
139         work1(); 
140         for (int i=1;i<=n;i++) a[i].x=50001-a[i].x;
141         sort(a+1,a+n+1);
142         work1();
143         printf("%s\n",flag ? "YES" : "NO" );
144     }
145 }
146 /*
147 5
148 1 1
149 1 2
150 1 3
151 2 1
152 3 3
153 */
View Code

 

转载于:https://www.cnblogs.com/rpSebastian/p/5755112.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值