hdu多校第九场 1002 (hdu6681) Rikka with Cake 树状数组维护区间和/离散化

题意:

在一块长方形蛋糕上切若干刀,每一刀都是从长方形某条边开始,垂直于这条边,但不切到对边,求把长方形切成了多少块。

题解:

块数=交点数+1

因为对于每个交点,唯一且不重复地对应着一块蛋糕。

就是产生这个交点的相互垂直的两刀,以及这两刀分别上次经过的刀痕或边缘,这四条边确定的长方形。

则问题转化成了求平面上,若干条平行于坐标轴的直线共有几个交点。

离散化后,记录横线的左右端点,竖线的上下端点,枚举横坐标,用树状数组记录这个横坐标上每一个点是否有横线经过。

求某条竖线与几条横线相交,就是在求区间和。

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
int countx,county;
int tree[100005]; 
int lowbit(int x){
    return x&(-x);
}
void add(int t,int p){//对x位置增加p;
    while(t<=county){
        tree[t]+=p;
        t+=lowbit(t);
    }
}
int getsum(int t){//1-x的和 ; 
    int res=0;
    while(t>0){
        res+=tree[t];
        t=t-lowbit(t);
    }
    return res;
}
int x[100005],y[100005],xx[100005],yy[100005];
char c[100005];
vector<int> ll[100005],rr[100005];
int uu[100005],dd[100005];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d %d %d",&n,&m,&k);
        for(int i=1;i<=k;i++){
            scanf("%d %d %c",&x[i],&y[i],&c[i]);
            xx[i]=x[i];
            yy[i]=y[i];
        }
        sort(xx+1,xx+k+1);
        sort(yy+1,yy+k+1);
        countx=unique(xx+1,xx+1+k)-1-xx;
        county=unique(yy+1,yy+1+k)-1-yy;
        for(int i=0;i<=countx;i++){
            uu[i]=dd[i]=0;
            ll[i].clear();rr[i].clear();
        }
        for(int i=1;i<=k;i++){
            x[i]=lower_bound(xx+1,xx+countx+1,x[i])-xx;
            y[i]=lower_bound(yy+1,yy+county+1,y[i])-yy;
            if(c[i]=='U'){
                uu[x[i]]=county;
                dd[x[i]]=y[i];
            }
            if(c[i]=='D'){
                uu[x[i]]=y[i];
                dd[x[i]]=1;
            }
            if(c[i]=='L'){
                ll[0].push_back(y[i]);
                rr[x[i]].push_back(y[i]);
            }
            if(c[i]=='R'){
                ll[x[i]].push_back(y[i]);
            }
        }
        int ans=0;
        memset(tree,0,sizeof tree);
        for(int i=0;i<=countx;i++){
            for(int j=0;j<ll[i].size();j++){
                add(ll[i][j],1);
            }
//            for(int i=1;i<=county;i++){
//                printf("%d ",getsum(i)-getsum(i-1));
//            }
//            printf("\n");
//            printf("%d %d\n",uu[i],dd[i]);
            ans+=getsum(uu[i])-getsum(dd[i]-1);
            for(int j=0;j<rr[i].size();j++){
                add(rr[i][j],-1);
            }
        }
        printf("%d\n",ans+1);
    }
    return 0;
}

PS:离散化的时间复杂度是O(nlogn),为了保证常数效率和代码整洁,应使用sort,unique和lower_bound三个标准函数

posted @ 2019-08-19 19:53  Isakovsky  阅读(273)  评论(0编辑  收藏  举报