hdu6681 Rikka with Cake(主席树)

题目链接
大意:给你一个矩形区域, ( ( 0 , 0 ) ( n , m ) ) ((0,0)-(n,m)) ((0,0)(n,m)),现在有k条直线,每条直线都是从一个点出发到上下左右四个方向之一。
问你这个区域被分成了多少块。
思路:稍微观察即可发现,分成的区域等于直线交点个数+1。
我们对 L , R L,R L,R方向的对纵坐标分开离散化建立主席树(横坐标放一起离散化),然后每次遍历 U , D U,D U,D方向的直线来在主席树上查询。
设当前横坐标为x
方向是U的话,那么L方向上横坐标x大于等于x的都为有效贡献,小于等于x的R方向都有贡献(纵坐标在范围内)。
方向的D的话,那么L方向上横坐标x大于等于x的都为有效贡献,小于等于x的R方向都有贡献(纵坐标在范围内)。
我们查询的时候分别对两个主席树进行查询,每次查询一个合法的纵坐标区间即可。
细节见代码

#include<bits/stdc++.h>

#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back

using namespace std;

LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 3e5 +11;
int t;
int n,m,k;
struct uzi
{
    int a,b;
    char c;
}p[N];
int a[N],b[N];
char c[N];
int cmp(uzi l,uzi r){
    return l.b<r.b;
}
struct fak{
    LL sum;
    int l,r;    
}T1[N*40],T2[N*40];
int n1,n2;
int t1[N],t2[N];
void up1(int l,int r,int &x,int y,int pos){
    T1[++n1]=T1[y];if(pos)T1[n1].sum++;x=n1;
    if(l==r)return ;
    int mid=l+r>>1;
    if(mid>=pos)up1(l,mid,T1[x].l,T1[y].l,pos);
    else up1(mid+1,r,T1[x].r,T1[y].r,pos);
}
void up2(int l,int r,int &x,int y,int pos){
    T2[++n2]=T2[y];if(pos)T2[n2].sum++;x=n2;
    if(l==r)return ;
    int mid=l+r>>1;
    if(mid>=pos)up2(l,mid,T2[x].l,T2[y].l,pos);
    else up2(mid+1,r,T2[x].r,T2[y].r,pos);
}
LL g1(int l,int r,int x,int y,int k){
    if(!x&&!y)return 0;
    if(r<k)return 0;
    if(l>=k)return T1[y].sum-T1[x].sum;;
    int mid=l+r>>1;
    return g1(l,mid,T1[x].l,T1[y].l,k)+g1(mid+1,r,T1[x].r,T1[y].r,k);
}
LL g2(int l,int r,int x,int y,int k){
    if(!x&&!y)return 0;
    if(l>k)return 0;
    if(r<=k)return (T2[y].sum-T2[x].sum);
    int mid=l+r>>1;
    return g2(l,mid,T2[x].l,T2[y].l,k)+g2(mid+1,r,T2[x].r,T2[y].r,k);
}
int PA[N],PB[N],La,Lb;
int main(){
    ios::sync_with_stdio(false);
    for(cin>>t;t;t--){
        cin>>n>>m>>k;
        n1=n2=0;
        La=0;Lb=0;
        for(int i=1;i<=k;i++){
            cin>>a[i]>>b[i]>>c[i];
            p[i]={a[i],b[i],c[i]};
            if(c[i]=='L')PA[++La]=b[i];
            if(c[i]=='R')PB[++Lb]=b[i];
        }
        sort(a+1,a+1+k);
        int r=unique(a+1,a+1+k)-a-1;
        sort(PA+1,PA+1+La);
        sort(PB+1,PB+1+Lb);
        La=unique(PA+1,PA+1+La)-PA-1;
        Lb=unique(PB+1,PB+1+Lb)-PB-1;
        for(int i=1;i<=k;i++){
            if(c[i]=='L'){
                p[i].b=lower_bound(PA+1,PA+1+La,p[i].b)-PA;
            }else if(c[i]=='R'){
                p[i].b=lower_bound(PB+1,PB+1+Lb,p[i].b)-PB;
            }
        }
        for(int i=1;i<=k;i++)p[i].a=lower_bound(a+1,a+1+r,p[i].a)-a;
        sort(p+1,p+1+k,cmp);
        for(int i=1;i<=k;i++){
            if(p[i].c=='L'){
                up1(0,r+1,t1[p[i].b],t1[p[i].b-1],p[i].a);
            }else if(p[i].c=='R'){
                up2(0,r+1,t2[p[i].b],t2[p[i].b-1],p[i].a);
            }
        }
        up1(0,r+1,t1[La+1],t1[La],0);
        up2(0,r+1,t2[Lb+1],t2[Lb],0);
        LL A=0;
        for(int i=1;i<=k;i++){
            if(p[i].c=='U'){
                int quL=lower_bound(PA+1,PA+1+La,p[i].b)-PA;
                int quR=lower_bound(PB+1,PB+1+Lb,p[i].b)-PB;
                A+=g1(0,r+1,t1[quL-1],t1[La+1],p[i].a);
                A+=g2(0,r+1,t2[quR-1],t2[Lb+1],p[i].a);
            }else if(p[i].c=='D'){
                int quL=upper_bound(PA+1,PA+1+La,p[i].b)-PA;
                int quR=upper_bound(PB+1,PB+1+Lb,p[i].b)-PB;    
                quL--;
                quR--;
                A+=g1(0,r+1,0,t1[quL],p[i].a);
                A+=g2(0,r+1,0,t2[quR],p[i].a);
            }
        }
        cout<<A+1<<endl;
    }
    return 0;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
2025-12-17 16:48
今天九点半到公司,我跟往常一样先扫了眼电脑,屁活儿没有。寻思着没事干,就去蹲了个厕所,回来摸出手机刷了会儿。结果老板刚好路过,拍了我一下说上班别玩手机,我吓得赶紧揣兜里。也就过了四十分钟吧,我的直属领导把我叫到小隔间,上来就给我一句:“你玩手机这事儿把老板惹毛了,说白了,你可以重新找工作了,等下&nbsp;HR&nbsp;会来跟你谈。”&nbsp;我当时脑子直接宕机,一句话都没憋出来。后面&nbsp;HR&nbsp;找我谈话,直属领导也在旁边。HR&nbsp;说我这毛病不是一次两次了,属于屡教不改,不光上班玩手机,还用公司电脑看论文、弄学校的事儿。我当时人都傻了,上班摸鱼是不对,可我都是闲得发慌的时候才摸啊!而且玩手机这事儿,从来没人跟我说过后果这么严重,更没人告诉我在公司学个习也算犯错!连一次口头提醒都没有,哪儿来的屡教不改啊?更让我膈应的是,昨天部门刚开了会,说四个实习生里留一个转正,让大家好好表现。结果今天我就因为玩手机被开了。但搞笑的是,开会前直属领导就把我叫去小会议室,明明白白告诉我:“转正这事儿你就别想了,你的学历达不到我们部门要求,当初招你进来也没打算给你这个机会。”合着我没入贵厂的眼是吧?可我都已经被排除在转正名单外了,摸个鱼至于直接把我开了吗?真的太离谱了!
rush$0522:转正名单没进,大概率本来就没打算留你
摸鱼被leader发现了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务