• 【NOIP2013模拟】小喵喵的新家


    Description
    小喵喵和小聪聪从小就是好朋友 ,他们经常在一起玩耍 。如今小喵已经厌倦了自己居住的环境,想请小聪聪为她建一个新家。

    小喵喵天生多才多艺,对多种乐器颇有研究。对于生活中常见的图形,她对圆形很感兴趣,因此小聪聪决定为她建一个圆形的新家。

    我们设新家在一个平面直角坐标系上,其中新家的圆心为平面直角坐标系的原点。

    小聪聪有一把神奇的剪刀,他定义了一个值m,以等分 [−pi,pi]弧度 (详见样例)。他还有一支神奇的画笔,将进行 n次“铺地毯”操作。对于第i 次“铺地毯”操作,他将设定一个半径ri,起始位置si,终止位置ti ,然后从圆心角pi*si/m到圆心角pi*ti/m这部分区域逆时针铺上一个扇形地毯。

    小喵喵想到了一个奇怪的问题,她想知道有多大面积被至少铺过k次地毯。 这个问题一下就难倒了聪明的小聪聪。 现在小聪聪求助于你,你能帮他解决这个问题吗?为了方便表达 ,设答案的值为T,你只需要输出 T×2m/pi的值即可 。

    Input
    第一行是三个整数 n,m,k,含义 如题目描述中所述。

    接下来n行, 每行描述一次铺地毯操作 。第i行有三个整数r,si,ti,含义 如 题目描述中所述。

    Output
    输出 一个整数 表示T×2m/pi的值。

    Sample Input
    3 8 2

    1 -8 8

    3 -7 3

    5 -5 5

    Sample Output
    76

    Data Constraint
    这里写图片描述

    Hint
    这里写图片描述
    .
    .
    .
    .
    .

    分析

    对于60%的做法:
    前6个点,直接上暴力,别怂
    对于后6个点,所有的半径都是相同的,直接用差分约束思想,在扇形开始为1,结束为-1
    做一遍前缀和,然后将大于等于k的区间的长度求出来,算面积
    对于100%的做法:
    扇形的面积:(所占的份数/2m)*πr^2
    题目说:答案要乘一个2m/π
    这样一相乘 化简:所占份数*r^2
    就不用考虑精度问题啦!!!(出题人好评)
    现在就要求出所有被覆盖大于等于k的面积,半径就是第k大的半径
    那一个部分中有什么半径,我们怎么知道呢?
    我们把圆拆成一条线段,端点就是圆圈上的各个等分点
    把地毯的半径视为高,连接起始点和终点,如果有横跨线段中点的,把它看作两个部分

    设g[r]为半径为r的数量
    我们可以从-m扫过去,碰到起始点的时候就把其对应的g[r]+1,碰到结束点的时候就把其对应的g[r]-1(也就类似与差分约束)

    现在就要求第k大值

    用线段树维护就好了
    .
    .
    .
    .
    .

    程序:
    #include<iostream>
    using namespace std;
    long long ans;
    int n,m,tj,r,s,k,t,p[500001],to[500001],head[200001],w[200001];
    
    struct edge 
    { 
        int a,b,c; 
    }e[500010];
    
    void cr(int x,int y) 
    { 
        e[++tj].a=x; e[tj].b=y; e[tj].c=r; 
    }
    
    void work(int l,int r,int d,int a,int b)
    {
        if (l==r) 
        {
            p[d]+=b;
            return;
        }
        int mid=(l+r)/2;
        if (a<=mid) work(l,mid,d*2,a,b); else work(mid+1,r,d*2+1,a,b);
        p[d]=p[d*2]+p[d*2+1];
    }
    
    int abs(int x) 
    { 
        if (x>=0) return x; else return -x+100000;
    }
    
    int find(int l,int r,int x,int k)
    {
        if (l==r) 
        {
            if (p[x]>=k) return l; else return 0;
        }
        int mid=(l+r)/2;
        if (p[x*2+1]>=k) return find(mid+1,r,x*2+1,k); else return find(l,mid,x*2,k-p[x*2+1]);
    }
    int main()
    {
        cin>>n>>m>>k;
        for (int i=1;i<=n;i++)
        {
            cin>>r>>s>>t;
            if (s==-m||s==m) 
            {
                cr(-m,1);
                cr(t,-1);
            } else
            {
                if (t==-m) t=m;
                if (t>=s) 
                {
                    cr(s,1);
                    cr(t,-1);
                } else 
                {
                    cr(s,1);
                    cr(m,-1);
                    cr(-m,1);
                    cr(t,-1);
                }
            }
        }
        for (int i=1;i<=tj;i++)
        {
            int j=abs(e[i].a);
            if (!head[j]) head[j]=i; else to[w[j]]=i;
            w[j]=i;
        }
        for (int i=-m;i<=m-1;i++)
        {
            for (int j=head[abs(i)];j!=0;j=to[j]) 
            work(1,100000,1,e[j].c,e[j].b);
            long long a=find(1,100000,1,k);
            ans+=a*a;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    转:JMeter5的If Controller操作解析
    .NET Core优秀的应用逻辑分层框架设计
    socket阻塞导致拿不到信息
    2018年开始了,我们还是说说2017吧
    PHP 学习 遇到坑的第一章
    记一次高并发情况,服务器和代码修改过程记录。
    IIS 提高连接的并发数,和CPU的使用率。
    2017年总结
    在 safari 浏览器 onclick 出现延迟的现象
    微信JS-api 注意事项
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499914.html
Copyright © 2020-2023  润新知