#4629. 世界

Posted xjqxjq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#4629. 世界相关的知识,希望对你有一定的参考价值。

题目描述

> 隔着一面墙,就是两个世界呢……
> 那无法到达的彼岸,只能去凝望吧……
> 远方的星辰,又能看到多少呢?
> 那一个个星星,或许也是一个个世界吧……

有一个虚无的结界,隔开了两个世界。

人们在结界内游荡,而远方的星辰在结界外。

我们可以把结界看作 $x$ 轴,那么人们都在 $x$ 轴下方,而星星都在 $x$ 轴上方。

人们本应该能看到所有的星星,但是结界外( $x$ 轴上方)出现了几座墙,挡住了人们的视线。墙是平行于 $x$ 轴的。

现在想问,每个人分别能看到多少星星。

数据范围

$nle 40000$,$mle 5$,$qle 40000$,坐标的绝对值不超过 $10^6$。

题解

考虑只有一堵墙的话,可以把星星和人分别对墙的两个端点做延长线到x轴上,那人看不到星星应当是星星的区间包含人的区间。于是就是个二位偏序。

考虑多堵墙,容斥即可。具体的就是星星和人对状态为 $1$ 的墙的区间取个交集,那如果人不能通过这些墙的任意一个看到星星的条件也是星星的区间包含人的区间。

代码

#include <bits/stdc++.h>
#define db long double
#define _(d) while(d(isdigit(c=getchar())))
using namespace std;
int D(){
    char c;int x,f=0;_(!)f|=(c==45);x=c^48;_()x=(x<<3)+(x<<1)+(c^48);return f?-x:x;
}
const int N=8e4+5;
int n,m,q,t,f[N],a[N],G,h[35];
db g[N];
struct O{
    int x,y,z;
}sr[N],wl[7],pr[N];
struct P{
    db l,r;int x;
}p[N];
inline db L(O u,O v){
    return ((db)u.x*v.z-(db)v.x*u.y)/((db)v.z-u.y);
}
inline db R(O u,O v){
    return ((db)u.x*v.z-(db)v.y*u.y)/((db)v.z-u.y);
}
bool cmp(P A,P B){
    return A.l==B.l?A.x<B.x:A.l<B.l;
}
inline void upd(int x){
    for (;x;x-=x&-x) a[x]++;
}
inline int qry(int x){
    int v=0;
    for (;x<=G;x+=x&-x) v+=a[x];
    return v;
}
inline void work(int s){
    t=0;
    for (int i=1;i<=n;i++){
        db l=-2e18,r=2e18;
        for (int j=1;j<=m;j++)
            if (s&(1<<(j-1))){
                if (sr[i].y<=wl[j].z){
                    r=l-1;break;
                }
                db x=L(sr[i],wl[j]),y=R(sr[i],wl[j]);
                l=max(x,l);r=min(r,y);
            }
        if (l<=r) p[++t]=(P){l,r,0},g[t]=r;
    }
    for (int i=1;i<=q;i++){
        db l=-2e18,r=2e18;
        for (int j=1;j<=m;j++)
            if (s&(1<<(j-1))){
                db x=L(pr[i],wl[j]),y=R(pr[i],wl[j]);
                l=max(x,l);r=min(r,y);
            }
        if (l<=r) p[++t]=(P){l,r,i},g[t]=r;
    }
    sort(p+1,p+t+1,cmp);
    sort(g+1,g+t+1);G=unique(g+1,g+t+1)-g-1;
    for (int r,i=1;i<=t;i++){
        r=lower_bound(g+1,g+G+1,p[i].r)-g;
        if (p[i].x) f[p[i].x]+=h[s]*qry(r);
        else upd(r);
    }
    for (int i=1;i<=G;i++) a[i]=0;
}
void W(int x){
    if (x<10) putchar(x^48);
    else W(x/10),putchar((x%10)^48);
}
int main(){
    n=D(),m=D(),q=D();h[0]=-1;
    for (int i=1;i<=n;i++)
        sr[i].x=D(),sr[i].y=D();
    for (int i=1;i<=m;i++)
        wl[i].x=D(),wl[i].y=D(),wl[i].z=D();
    for (int i=1;i<=q;i++)
        pr[i].x=D(),pr[i].y=D();
    for (int i=1;i<(1<<m);i++) h[i]=-h[i-(i&-i)];
    for (int i=(1<<m)-1;i;i--) work(i);
    for (int i=1;i<=q;i++) W(n-f[i]),putchar(
);
    return 0;
}

 

以上是关于#4629. 世界的主要内容,如果未能解决你的问题,请参考以下文章

根据顶点世界位置Y坐标修改Metal片段着色

你可能不知道的JavaScript代码片段和技巧(下)

你可能不知道的JavaScript代码片段和技巧(上)

寥寥几行代码,却改变了世界!

带有标记的Android谷歌地图片段

GLSL-片段着色器不同部分的精度不同