Hang on electricity more than 2019 school ⑨ field B Rikka with Cake (Chairman of the tree, discrete)

Meaning of the questions:

Given an n * m rectangular area, there are several points in the region, each vertex emit a radiation, there are four vertical and horizontal directions, ask rectangular region is divided into several?

Ideas:

A little observation and enumeration can be found, the number of areas = +1 beam cross-points (Euler's theorem can be used to verify, but I will not), the problem is converted into the number of statistics ray intersection

Rays can be separated in four directions, with intersecting to query about the number of radiation rays and vertically, first consider the left-ray A and ray intersects several upward, provided A (x, y), i.e., seeking (1 inside, x) range \ (\ le y \) rays upwards of several, apparently Chairman tree can be used for maintenance (can also be used Fenwick tree and faster, but I will not). Similarly other cases, pay attention to close up or close down when the discrete

Since y is in the range of (1,1e9), so y discretization needed, because the nature of the President of the tree, x be sorted discretization

//memory= 1.3e8 int
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
const int N=1e5+2;
int xu[maxn],xd[maxn],yu[maxn],yd[maxn];
int x1[maxn],y1[maxn];
char c1[maxn];
const int Log=50;
int root[2][maxn],num[2][maxn*Log],lson[2][maxn*Log],rson[2][maxn*Log];
int tot[2];
double Sum,Num;
int build(int id,int l,int r){
    int root=++tot[id];
    num[id][root]=0;
    if(l<r){
        int mid=(l+r)>>1;
        lson[id][root]=build(id,l,mid);
        rson[id][root]=build(id,mid+1,r);
    }
    return root;
}
int update(int id,int pre,int l,int r,int x){
    int root=++tot[id];
    num[id][root]=num[id][pre]+1;
    lson[id][root]=lson[id][pre];
    rson[id][root]=rson[id][pre];
    if(l<r){
        int mid=(l+r)>>1;
        if(x<=mid) lson[id][root]=update(id,lson[id][pre],l,mid,x);
        else rson[id][root]=update(id,rson[id][pre],mid+1,r,x);
    }
    return root;
}
int query(int id,int Old,int New,int l,int r,int k){//Old和New对应旧版本的根和新版本的根
    if(id==0){//向上,查区间内<=k的数的个数 
        if(r<=k){
            return num[id][New]-num[id][Old];
        }
        int mid=(l+r)>>1;
        int res=0;
        if(l<=k) res+=query(id,lson[id][Old],lson[id][New],l,mid,k);
        if(mid+1<=k) res+=query(id,rson[id][Old],rson[id][New],mid+1,r,k);
        return res;
    }
    else{//向下,查区间内>=k的数的个数
        if(l>=k){
            return num[id][New]-num[id][Old];
        }
        int mid=(l+r)>>1;
        int res=0;
        if(mid>=k) res+=query(id,lson[id][Old],lson[id][New],l,mid,k);
        if(r>=k) res+=query(id,rson[id][Old],rson[id][New],mid+1,r,k);
        return res;
    }
}
struct node{
    node(int a,int b):x(a),y(b){}
    int x,y;
};
bool cmp(node a,node b){
    return a.x<b.x;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        tot[0]=tot[1]=0;
        int n,m,k;
        vector<node> U,D,R,L;
        scanf("%d%d%d",&n,&m,&k);
        int x,y;
        char c;
        int sizexu=0,sizeyu=0,sizexd=0,sizeyd=0;
        for(int i=1;i<=k;i++){
            scanf("%d%d %c",&x,&y,&c);
            x1[i]=x;y1[i]=y;c1[i]=c;
            if(c=='U') xu[++sizexu]=x,yu[++sizeyu]=y;
            if(c=='D') xd[++sizexd]=x,yd[++sizeyd]=y;
        }
        sort(xu+1,xu+1+sizexu);sort(yu+1,yu+1+sizeyu);
        sort(xd+1,xd+1+sizexd);sort(yd+1,yd+1+sizeyd);
        sizexu=unique(xu+1,xu+1+sizexu)-(xu+1);
        sizexd=unique(xd+1,xd+1+sizexd)-(xd+1);
        sizeyu=unique(yu+1,yu+1+sizeyu)-(yu+1);
        sizeyd=unique(yd+1,yd+1+sizeyd)-(yd+1);
        for(int i=1;i<=k;i++){//U,D中存离散化的坐标值。L,R存原值,之后再在对应数组中二分找离散值
            if(c1[i]=='U'){
                x1[i]=lower_bound(xu+1,xu+1+sizexu,x1[i])-xu;
                y1[i]=lower_bound(yu+1,yu+1+sizeyu,y1[i])-yu;
                U.push_back(node(x1[i],y1[i]) );
            }
            if(c1[i]=='D'){
                x1[i]=lower_bound(xd+1,xd+1+sizexd,x1[i])-xd;
                y1[i]=lower_bound(yd+1,yd+1+sizeyd,y1[i])-yd;
                D.push_back(node(x1[i],y1[i]) );
            }
            if(c1[i]=='L') L.push_back(node(x1[i],y1[i]) );
            if(c1[i]=='R') R.push_back(node(x1[i],y1[i]) );
        }
        //建2棵主席树,分别存U,D,再用L和R取查找
        root[0][0]=build(0,1,N);
        root[1][0]=build(1,1,N);
        sort(U.begin(),U.end(),cmp);
        for(int i=0;i<U.size();i++)
            root[0][i+1]=update(0,root[0][i],1,N,U[i].y);
        sort(D.begin(),D.end(),cmp);
        for(int i=0;i<D.size();i++)
            root[1][i+1]=update(1,root[1][i],1,N,D[i].y);
        int ans=0;
        for(int i=0;i<L.size();i++){
            int r0=upper_bound(xu+1,xu+1+sizexu,L[i].x)-xu-1;//找<=,向左靠近
            int r1=upper_bound(xd+1,xd+1+sizexd,L[i].x)-xd-1;//找<=,向左靠近
            int h0=upper_bound(yu+1,yu+1+sizeyu,L[i].y)-yu-1;//找<=,向下靠近
            int h1=lower_bound(yd+1,yd+1+sizeyd,L[i].y)-yd;//找 >=,向上靠近
            ans+=query(0,root[0][0],root[0][r0],1,N,h0);
            ans+=query(1,root[1][0],root[1][r1],1,N,h1);
        }
        for(int i=0;i<R.size();i++){
            int l0=lower_bound(xu+1,xu+1+sizexu,R[i].x)-xu;//找>=,向右靠近
            int l1=lower_bound(xd+1,xd+1+sizexd,R[i].x)-xd;//找>=,向右靠近
            int h0=upper_bound(yu+1,yu+1+sizeyu,R[i].y)-yu-1;//找<=,向下靠近
            int h1=lower_bound(yd+1,yd+1+sizeyd,R[i].y)-yd;//找 >=,向上靠近
            ans+=query(0,root[0][l0-1],root[0][U.size()],1,N,h0);
            ans+=query(1,root[1][l1-1],root[1][D.size()],1,N,h1);
        }
        printf("%d\n",ans+1);
    }
}

Guess you like

Origin www.cnblogs.com/ucprer/p/11388097.html