zoukankan      html  css  js  c++  java
  • [NOI2005] 月下柠檬树

    题意:

    给定一棵由若干个圆台和圆锥组成的树,求这棵树在与地面成$alpha$角的平行光束照射下产生的投影的面积。

    $nleq 500$。

    题解:

    显然投影下去之后每个圆的$r$不变,而高度$h$变成$frac{h}{ an{alpha}}$。

    圆的面积可以直接算,两个圆的公切线形成的梯形用三角函数推一下也可以直接算。

    那么直接$Simpson$积分算一下就行了。注意区间$l,r$应该对所有圆算一遍$min,max$来取值,因为会出现圆套圆的情况。

    复杂度$O(n^{2}log{n})$(大概吧)。

    套路:

    • 求一个整体复杂但可以求得单点极值的图形面积$ ightarrow$Simpson积分。

    代码:

    #include<bits/stdc++.h>
    #define maxn 200005
    #define maxm 500005
    #define inf 0x7fffffff
    #define eps 1e-6
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    int n; double H[maxn],R[maxn],C[maxn];
    
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline double f(double x){
        double res=0; 
        for(rint i=1;i<=n;i++)
            if(C[i]-x<R[i] && C[i]-x>-R[i])
                res=max(res,sqrt(R[i]*R[i]-(C[i]-x)*(C[i]-x)));
        for(rint i=1;i<n;i++){
            double x1=C[i]+R[i]*(R[i]-R[i+1])/H[i];
            double x2=C[i+1]+R[i+1]*(R[i]-R[i+1])/H[i];
            if(x1<x && x2>x){
                double y1=sqrt(R[i]*R[i]-(C[i]-x1)*(C[i]-x1));
                double y2=sqrt(R[i+1]*R[i+1]-(C[i+1]-x2)*(C[i+1]-x2));
                res=max(res,y1+(x-x1)*(y2-y1)/(x2-x1));
            }
        }
        return res;
    }
    
    inline double simpson(double l,double r){return (r-l)*(f(l)+f(r)+4.0*f((l+r)/2.0))/6.0;}
    inline double solve(double l,double r){
        double mid=(l+r)/2.0,S=simpson(l,r),S1=simpson(l,mid),S2=simpson(mid,r);
        return (abs(S1+S2-S)<eps)?(S1+S2):(solve(l,mid)+solve(mid,r));
    }
    
    int main(){
        n=read(); double theta; 
        scanf("%lf",&theta); 
        double tp=tan(theta);
        for(rint i=0;i<=n;i++) scanf("%lf",&H[i]),H[i]/=tp;
        for(rint i=1;i<=n;i++) scanf("%lf",&R[i]); 
        R[++n]=eps,C[1]=R[1]; 
        for(rint i=2;i<=n;i++) C[i]=C[i-1]+H[i-1];
        double l=0,r=0; 
        for(rint i=1;i<=n;i++) r=max(r,C[i]+R[i]),l=min(l,C[i]-R[i]);
        printf("%.2lf
    ",solve(l,r)*2.0);
        return 0;
    }
    月下柠檬树
  • 相关阅读:
    020-请你说一说app测试的工具
    栈的压入、弹出序列
    包含min函数的栈
    顺时针打印矩阵
    二叉树的镜像
    树的子结构
    链表中倒数第k个结点
    调整数组顺序使奇数位于偶数前面
    数值的整数次方
    矩形覆盖
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13195554.html
Copyright © 2011-2022 走看看