hdu5820(可持久化线段树)

Lights

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1146    Accepted Submission(s): 300

Problem Description

Today is April 1st, 2100. Now Guangzhou is a very very big city. Since the number of traffic accidents increased last month, the mayor asked Mr. Chopsticks to investigate the traffic condition of the city. 
After studying the map of Guangzhou for a while, Mr. Chopsticks has some ideas. Guangzhou can be considered as a rectangular grid with 50000 horizontal streets running west-east (labeled with y-coordinates from 1 to 50000) and 50000 vertical streets running north-south (labeled with x-coordinates from 1 to 50000). All streets are two-way streets. A crossroad is an intersection of a horizontal street and a vertical street, so a crossroad can be represented by (x, y), where x and y are coordinates of the horizontal street and vertical street respectively. Since there are too many streets, traffic lights are not placed at all crossroads. Given two crossroads (x1, y1) and (x2, y2), a path between these two crossroads is said to be good if the length of the path is |x1 – x2| + |y1 – y2| and there exist a traffic light at each turn of this path. Of course, a path must be along the streets, and a turn can only be at a crossroad.
Now given locations of all traffic lights in Guangzhou, Mr. Chopsticks wants to check whether there exists at least one good path between every pair of traffic lights. As Mr. Chopsticks is busy in preparing ACMICPC 2100, he asks you for help.

Input

The input contains multiple test cases. Each case begins with an integer N (1 <= N <= 500000), indicating the number of traffic lights. The following N lines each contain two integers x and y (1 <= x, y <= 50000), indicating a location of a traffic light. There may be multiple traffic lights at the same location.

N = 0 indicates the end of the input.

Output

For each case, output “YES” if there exists at least one good path between every pair of traffic lights; otherwise output “NO”.

Sample Input

2

1 1

3 3

3

1 1

1 3

3 3

0

Sample Output

NO

YES

 

题目大意

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

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

将按x正这排序来一遍倒着排序来一遍

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<map>
    #include<algorithm>
    using namespace std;
    const int maxn = 500010;
    const int maxy = 50010;
    map<int,int>mp;
    map<int,int>near_x;
    struct node
    {
        int x, y;
    }st[maxn];
    bool cmp(node a,node b){
        if(a.x==b.x)return a.y<b.y;
        return a.x<b.x;
    } 
    struct  tre
    {
        int chl,chr;
        int cnt;
    }t[1000010*8];
    int root[maxn];
    int tot = 0;
    void build(int &x,int l,int r) {
        x=++tot;
        t[x].cnt = 0;   
        if (l==r) return ;
        int mid=(l+r)>>1;
        build(t[x].chl,l,mid); build(t[x].chr,mid+1,r);
    }
    void insert(int &x,int rot,int key,int l,int r) {
        x=++tot;
        t[x].chl=t[rot].chl;
        t[x].chr=t[rot].chr;
        t[x].cnt=t[rot].cnt+1;
        if (l==r) {
            return ;
        }
        int mid=(l+r)>>1;
        if (key>mid) {
            insert(t[x].chr,t[rot].chr,key,mid+1,r);
        } else {
            insert(t[x].chl,t[rot].chl,key,l,mid);
        }
    }
    int query(int a,int b,int l,int r,int ql,int qr)
    {
        if(l>=ql&&r<=qr)return t[b].cnt - t[a].cnt;
        int mid = (l+r)>>1;
        int suml = 0;
        int sumr =  0;
        if(ql<=mid)suml = query(t[a].chl,t[b].chl,l,mid,ql,qr);
        if(qr>mid)sumr = query(t[a].chr,t[b].chr,mid+1,r,ql,qr);
        return suml+sumr;
    }

    int main()
    {
        int n;
        while(~scanf("%d",&n)&&n)
        {
            tot = 0;
            mp.clear();
            near_x.clear();
            int num = 0;
            for(int i =  0;i<n;i++)
            {
                scanf("%d%d",&st[i].x,&st[i].y);
            }
            sort(st,st+n,cmp);
            for(int i = 0;i<n;i++)
            {
                if(!mp[st[i].x])
                    mp[st[i].x] = ++num;
            }
            build(root[0],1,50010);
            int last = root[0];
            bool flag = 1;
            int near_rt;
            int near_y;
            for(int i = 0;i<n;i++)
            {
                if(i>0&&st[i].x==st[i-1].x&&st[i].y==st[i-1].y)continue;
                insert(root[mp[st[i].x]],last,st[i].y,1,50010);
                last = root[mp[st[i].x]];
                near_rt = mp[near_x[st[i].y]];
                if(i == 0||st[i].x!=st[i-1].x)near_y = 0;
                else near_y = st[i-1].y;
                if(near_y+1<=st[i].y-1&&query(root[near_rt],root[mp[st[i].x]],1,50010,near_y+1,st[i].y-1))
                {
                    flag = false;
                    break;
                }
                near_x[st[i].y] = st[i].x;
            }
            for(int i = 0;i<n;i++)st[i].x = 50001-st[i].x;
            sort(st,st+n,cmp);
            mp.clear();
            near_x.clear();
            for(int i = 0;i<n;i++)
            {
                if(!mp[st[i].x])
                    mp[st[i].x] = ++num;
            }
            tot = 0;
            build(root[0],1,50000);
            last = root[0];
            for(int i = 0;i<n;i++)
            {
                if(i>0&&st[i].x==st[i-1].x&&st[i].y==st[i-1].y)continue;
                insert(root[mp[st[i].x]],last,st[i].y,1,50010);
                last = root[mp[st[i].x]];
                near_rt = mp[near_x[st[i].y]];
                if(i == 0||st[i].x!=st[i-1].x)near_y = 0;
                else near_y = st[i-1].y;
                if(near_y+1<=st[i].y-1&&query(root[near_rt],root[mp[st[i].x]],1,50010,near_y+1,st[i].y-1))
                {
                    flag = false;
                    break;
                }
                near_x[st[i].y] = st[i].x;
            }
            if(!flag)
                printf("NO\n");
            else 
                printf("YES\n");
        }
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值