多校赛第7场 hdu5820 Lights 主席树

hdu5820 Lights

比赛时候卡在一个构造题上了,结束改了一行1A,心痛。。

没有时间看别的题,这是个很严重的问题。。

题意

一个50000x50000的网格,上面有500000个红绿灯(整点),问这些红绿灯两两之间是否都有一条这样的路,使得路上每个转弯点都有交通灯。

解法

题解上感觉写的有点问题。

对于每个交通灯,找到距离它最近的上下左的交通灯(若没有则视为边界有),由这四个点可以构成一个矩形。

这个矩形有一个特点:矩形边界的点符合条件,而矩形内部的点则到前面选的那个点不存在那条路。

所以问题转化为了,看那个矩形内部是否有点。点范围很小,不需要离散化,直接用主席树维护,主席树T[y]维护,对于前y列,x座标在[x1 ,x2 ]中点的数目。

那么矩形{(x1 ,y1 ),(x2 ,y2 )}内部点数为:

query(T[y2-1],x1,x2 ) - query(T[y1],x1,x2)

代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

 const int N = 50000;

namespace PST {

    const int MAXN = 50010;
    const int M = MAXN * 160;
    int tot;
    int T[M],lson[M],rson[M],c[M];
    int n;
    void init(int _n) {
        tot = 0;
        n = _n;
    }
    int build(int l = 1,int r = n)
    {
        int root = tot++;
        c[root] = 0;
        if(l != r)
        {
            int mid = (l+r)>>1;
            lson[root] = build(l,mid);
            rson[root] = build(mid+1,r);
        }
        return root;
    }
    int update(int root,int pos,int val)
    {
        int newroot = tot++, tmp = newroot;
        c[newroot] = c[root] + val;
        int l = 1, r = n;
        while(l < r)
        {
            int mid = (l+r)>>1;
            if(pos <= mid)
            {
                lson[newroot] = tot++; rson[newroot] = rson[root];
                newroot = lson[newroot]; root = lson[root];
                r = mid;
            }
            else
            {
                rson[newroot] = tot++; lson[newroot] = lson[root];
                newroot = rson[newroot]; root = rson[root];
                l = mid+1;
            }
            c[newroot] = c[root] + val;
        }
        return tmp;
    }
    int query(int root, int l, int r, int s = 1, int t = n) {
        //查询区间和
        //printf("l=%d r=%d\n",l,r);
        if(l > r) return 0;
        int mid = (s + t) / 2;
        if(l == s && r == t) return c[root];
        else if(r <= mid) return query(lson[root], l, r, s, mid);
        else if(l > mid) return query(rson[root], l, r, mid+1,t);
        else return query(lson[root],l,mid,s,mid) + query(rson[root],mid+1,r,mid+1,t);
    }
}

const int SIZE = PST::MAXN;
vector<int> B[SIZE];

int lef[SIZE];

int init() {
    for(int i = 1; i <= N; i++) {
        sort(B[i].begin(), B[i].end());
        B[i].erase(unique(B[i].begin(), B[i].end()), B[i].end());
    }
    PST::init(N);
    PST::T[0] = PST::build();
    memset(lef, 0, sizeof(lef));
}

bool solve() {
    for(int i = 1; i <= N; i++) {
        PST::T[i] = PST::T[i-1];
        for(int j = 0; j < B[i].size(); j++) {
            int high = !j? 0: B[i][j-1]; // 正上方
            int low = j == B[i].size() - 1? N + 1: B[i][j+1]; // 正下方
            if(PST::query(PST::T[i], high + 1, low - 1) - PST::query(PST::T[lef[B[i][j]]], high + 1, low - 1)) return false;
        }
        for(int j = 0; j < B[i].size(); j++) {
            PST::T[i] = PST::update(PST::T[i], B[i][j], 1);
            lef[B[i][j]] = i;
        }
    }
    return true;
}

int main() {
    int n;
    while(~scanf("%d",&n) && n) {
        for(int i = 1; i <= N; i++) B[i].clear();
        while(n--) {
            int a, b;
            scanf("%d%d",&a,&b);
            B[a].push_back(b);
        }
        init();
        printf("%s\n",solve()?"YES":"NO");
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章