zoukankan      html  css  js  c++  java
  • 世界

    世界

    【题目背景】

    隔着一面墙,就是两个世界呢……

    那无法到达的彼岸,只能去凝望吧……

    远方的星辰,又能看到多少呢?

    那一个个星星,或许也是一个个世界吧……

    【题目描述】

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

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

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

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

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

    输入格式

    第一行三个数,n,m,qn,m,q,表示星星的数量,墙数,人数。

    下面 nn 行,每行两个整数 x,yx,y,表示星星的坐标,其中 y>0y>0

    下面 mm 行,每行三个整数 x_1,x_2,yx1,x2,y,表示两端的 xx 坐标和 yy 坐标。其中 y>0,x_1<x_2y>0,x1<x2

    下面 qq 行,每行两个整数 x,yx,y,表示人的坐标,其中 y<0y<0 。

    坐标的绝对值不超过 10^6106 。

    数据保证星星和墙不重叠。

    输出格式

    qq 行,第 ii 行一个数表示第 ii 个人能看到的星星数量。

    样例

    样例输入1

    6 2 3
    0 2
    0 15
    5 7
    15 15
    35 12
    45 10
    5 20 5
    25 40 10
    0 -5
    5 -10
    20 -15

    样例输出1

    4
    3
    2

    样例解释

    样例解释图如下:

    数据范围与提示

    测试点编号nnmmqq
    1~3 le 10001000 le 55 le 10001000
    4~6 le 4000040000 =1=1 le 4000040000
    7~10 le 4000040000 le 55 le 4000040000

    来源

    CSP-S 2019模拟 淮阴


    Solution
    有一个很妙的转化:
    连接一块板的两端和人,所得的线交x轴与l,r
    连接一块板的两端和星星,所得的线交x轴与L,R
    那么人看不到星星当且仅当L<=l<r<=R
    m=1时就是类似二位偏序的统计了。
    m>1时可以2^5枚举板,考虑板的交集容斥即可。
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 40005
    #define inf 1e16
    #define db double
    using namespace std;
    int n,m,q,fl[6],tot,sb,sc,ans[maxn],Max,tr[maxn*4];
    db p[maxn*4];
    struct node{
        int id;db x,y;
        int l,r;
    }a[6][2],s[maxn],t[maxn],b[maxn],c[maxn];
    int read(){
        char ch;int v=0,f=1;
        while(!isdigit(ch=getchar())&&ch!='-');
        if(ch=='-')f=-1;else v=v+ch-48;
        while(isdigit(ch=getchar()))v=(v<<1)+(v<<3)+ch-48;
        return v*f;
    }
    db cr(node A,node B){
        if(A.x==B.x)return A.x;
        db k=(A.y-B.y)/(A.x-B.x);
        db tmp=-A.y/k+A.x;return tmp;
    }
    int find(db x){
        int l=1,r=tot;
        while(l<r){
            int mid=l+r+1>>1;
            if(p[mid]<=x)l=mid;
            else r=mid-1;
        }
        return l;
    }
    void init(){
        sb=sc=0;tot=0;
        for(int i=1;i<=n;i++){
            db L=-inf,R=inf;
            for(int j=1;j<=m;j++){
                if(!fl[j])continue;
                L=max(L,cr(a[j][0],s[i]));R=min(R,cr(a[j][1],s[i]));
                
            }
            if(L<=R){
                node x;x.x=L,x.y=R;
                b[++sb]=x,p[++tot]=L,p[++tot]=R;
            }
        }
        for(int i=1;i<=q;i++){
            db L=-inf,R=inf;
            for(int j=1;j<=m;j++){
                if(!fl[j])continue;
                L=max(L,cr(a[j][0],t[i]));R=min(R,cr(a[j][1],t[i]));
            }
            if(L<=R){
                node x;x.id=t[i].id;x.x=L,x.y=R;
                c[++sc]=x,p[++tot]=L,p[++tot]=R;
            }
        }
        if(!sb||!sc)return;
        sort(p+1,p+tot+1);tot=unique(p+1,p+tot+1)-p-1;
        Max=0;
        for(int i=1;i<=sb;i++){
    //        b[i].l=lower_bound(p+1,p+tot+1,b[i].x)-p;
    //        b[i].r=lower_bound(p+1,p+tot+1,b[i].y)-p;
            b[i].l=find(b[i].x);b[i].r=find(b[i].y);
            Max=max(Max,b[i].r);
        }
        for(int i=1;i<=sc;i++){
    //        c[i].l=lower_bound(p+1,p+tot+1,c[i].x)-p;
    //        c[i].r=lower_bound(p+1,p+tot+1,c[i].y)-p;
            c[i].l=find(c[i].x),c[i].r=find(c[i].y);
            Max=max(Max,c[i].r);
        }
    }
    bool cmp(node A,node B){return A.l<B.l;}
    void add(int i,int v){for(;i<=Max;i+=i&-i)tr[i]+=v;}
    int ask(int i){int sum=0;for(;i;i-=i&-i)sum+=tr[i];return sum;}
    void clac(int op){
        init();if(!sb||!sc)return;
        sort(b+1,b+sb+1,cmp);
        sort(c+1,c+sc+1,cmp);
        for(int i=1;i<=Max;i++)tr[i]=0;
        int j=1;
        for(int i=1;i<=sc;i++){
            while(j<=sb&&b[j].l<=c[i].l)add(b[j].r,1),j++;
            int tmp=ask(Max)-ask(c[i].r-1);
            if(op)ans[c[i].id]+=tmp;
            else ans[c[i].id]-=tmp;
        }
    }
    int main(){
        n=read();m=read();q=read();
        for(int i=1;i<=n;i++)s[i].x=read(),s[i].y=read();
        for(int i=1;i<=m;i++)a[i][0].x=read(),a[i][1].x=read(),a[i][0].y=a[i][1].y=read();
        for(int i=1;i<=q;i++)t[i].x=read(),t[i].y=read(),t[i].id=i;
        for(int S=1;S<(1<<m);S++){
            int co=0;
            for(int i=0;i<m;i++)if(S&(1<<i))fl[i+1]=1,co++;
            clac(co&1);
            for(int i=1;i<=m;i++)fl[i]=0; 
        }
        for(int i=1;i<=q;i++)printf("%d
    ",n-ans[i]);
        return 0;
    }
     
     
     
  • 相关阅读:
    Http 请求处理流程
    ASP.NET 4.0: 请求验证模式变化导致ValidateRequest=false失效
    Android Animation学习笔记【转载】
    Http Handler 介绍
    对路径XXX的访问被拒绝(文件操作权限)的解决方法
    控制页面滚动条
    Sqlserver查询字段默认值
    Ajax基础
    浮动&定位
    定时器
  • 原文地址:https://www.cnblogs.com/liankewei/p/11846529.html
Copyright © 2011-2022 走看看