ケーキと電気で2019以上の学校⑨フィールドBリッカインをハングアップ(木会長、離散)

質問の意味:

N * mの矩形領域指定された、いくつかの点が領域内に存在する各頂点が放射線を放射する、4つの縦方向と横方向があり、矩形領域は、いくつかに分割されている尋ねますか?

アイデア:

ほとんど観察および列挙は、領域数= +1ビームクロスポイント(オイラーの定理を確認するために使用することができ、私はない)、問題が統計線の交差点の数に変換される見つけることができます

光線は、すなわち、(1を求め、(x、y)を設け、放射線の数の問い合わせと垂直に、第1の左線Aを考慮し、光線が複数の上方を交差するように交差して、四方に分離することができます内部に、x)の範囲の\(\ルY \) いくつか、明らかに会長ツリーの線上向きがメンテナンスのために使用することができます(また)フェンウィックの木を使用し、より速く、私はしませんすることができます。同様に、他の例では、クローズアップ時や離散閉鎖に注意を払います

ツリーの大統領の性質は、X離散化をソートするためYは、必要に応じて(1,1e9)ので、Y離散化の範囲内であるので

//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);
    }
}

おすすめ

転載: www.cnblogs.com/ucprer/p/11388097.html