• HDU 4816 Bathysphere (2013长春现场赛D题)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816

    2013长春区域赛的D题。

    很简单的几何题,就是给了一条折线。 然后一个矩形窗去截取一部分,求最大面积。

    现场跪在这题,最后时刻TLE到死,用的每一小段去三分,时间复杂度是O(n log n) , 感觉数据也不至于超时。

    卧槽!!!!代码拷回来,今天在HDU一交,一模一样的代码AC了,加输入外挂6s多,不加也8s多,都可AC,呵呵·····(估计HDU时限放宽了!!!)

    现场赛卡三分太SXBK了,我艹!!!! 好好的一个现场赛绝杀错过了。

    以下是现场赛源码,在HDU顺利AC! 现场TLE到死!

    其实O(n)也可以搞,因为是三分的是一个二次函数,求对称轴就可以了。现场没有想到这个优化,等下简单修改成O(n)代码。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <map>
      7 #include <set>
      8 #include <vector>
      9 #include <string>
     10 #include <math.h>
     11 using namespace std;
     12 const int MAXN = 200010;
     13 int x[MAXN],y[MAXN];
     14 int d;
     15 int n;
     16 int L;
     17 int nowx ;
     18 int nextx;
     19 int r1,l2;
     20 const double eps = 1e-8;
     21 double solve()
     22 {
     23     double left = nowx,right = nextx;
     24     double ret1,ret2;
     25     for(int cc = 0;cc <= 30;cc++)
     26     {
     27         double mid = (left + right)/2;
     28         double midmid = (mid + right)/2;
     29         double h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (mid  - x[r1])/(x[r1-1] - x[r1]);
     30         double h2 = y[l2] + (double)(y[l2+1] - y[l2])*(mid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
     31         ret1 = (double)(x[r1] - mid)*(h1 + y[r1])/2 + (double)(mid + 2*d - x[l2])*(h2 + y[l2])/2;
     32         
     33          h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (midmid  - x[r1])/(x[r1-1] - x[r1]);
     34          h2 = y[l2] + (double)(y[l2+1] - y[l2])*(midmid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
     35         ret2 = (double)(x[r1] - midmid)*(h1 + y[r1])/2 + (double)(midmid + 2*d - x[l2])*(h2 + y[l2])/2;
     36         if(ret1 < ret2)
     37             left = mid+eps;
     38         else right = midmid-eps;
     39     }
     40     return ret1;
     41 }
     42 
     43 
     44 int input()
     45 {
     46     char ch;
     47     ch = getchar();
     48     while(ch < '0' || ch >'9')
     49     {
     50         ch = getchar();
     51     }
     52     int ret = 0;
     53     while(ch >= '0' && ch <= '9')
     54     {
     55         ret *= 10;
     56         ret += ch -'0';
     57         ch = getchar();
     58     }
     59     return ret;
     60 }
     61 
     62 int main()
     63 {
     64     //freopen("D.txt","r",stdin);
     65     //freopen("out.txt","w",stdout);
     66     int T;
     67     scanf("%d",&T);
     68     while(T--)
     69     {
     70         scanf("%d%d",&n,&L);
     71         for(int i = 1;i <= n;i++)
     72         {
     73             //x[i] = input();
     74             //y[i] = input();
     75             scanf("%d%d",&x[i],&y[i]);
     76         }
     77             //scanf("%d%d",&x[i],&y[i]);
     78         scanf("%d",&d);
     79         double ans = 0;
     80          r1 = 2;
     81          l2 = 1;
     82         double tmp = 0;
     83         while(l2 < n && x[l2+1] < 2*d)l2++;
     84         for(int i = r1;i < l2;i++)
     85         {
     86             tmp += (double)(x[i+1] - x[i])*(y[i] + y[i+1])/2;
     87         }
     88         if(l2  == 1)
     89         {
     90             tmp -= (double)(x[2] - x[1])*(y[2] + y[1])/2;
     91         }
     92         x[n+1] = x[n];
     93         y[n+1] = y[n];
     94         nowx = 0;
     95         //printf("%d %d
    ",r1,l2);
     96         while(l2 < n && r1 <= n)
     97         {
     98             int p1 = x[r1];
     99             int p2 = x[l2 + 1] - 2*d;
    100             if(p1 < p2)
    101                 nextx = p1;
    102             else nextx = p2;
    103             nextx = min(L- 2*d,nextx);
    104             //printf("%d %d
    ",nowx,nextx);
    105             ans = max(ans,tmp + solve());
    106             if(p1 < p2)
    107             {
    108                 nowx = p1;
    109                 if(r1 < n)tmp -= (double)(x[r1+1] - x[r1])*(y[r1+1] + y[r1] )/2;
    110                 r1++;
    111             }
    112             else
    113             {
    114                 nowx = p2;
    115                 tmp += (double)(x[l2+1] - x[l2])*(y[l2+1] + y[l2])/2;
    116                 l2++;
    117             }
    118         }
    119         printf("%.3lf
    ",ans/2/d);
    120     }
    121     return 0;
    122 }

     改成了O(n)的解法。

    因为三分的那个函数是二次函数。

    找最大值,只要找两个端点和对称轴处就足够了!

    还是太弱,现场没有想到这个优化,改起来很容易的。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <map>
      7 #include <set>
      8 #include <vector>
      9 #include <string>
     10 #include <math.h>
     11 using namespace std;
     12 const int MAXN = 200010;
     13 int x[MAXN],y[MAXN];
     14 int d;
     15 int n;
     16 int L;
     17 int nowx ;
     18 int nextx;
     19 int r1,l2;
     20 const double eps = 1e-8;
     21 double solve()
     22 {
     23     double left = nowx,right = nextx;
     24     //求出二次函数的a,b,c系数
     25     double tmp11 = x[r1];
     26     double tmp12 = -1;
     27     double tmp13 = (double)y[r1] - (double)x[r1]*(y[r1-1] - y[r1])/(x[r1-1] - x[r1])/2;
     28     double tmp14 = (double)(y[r1-1] - y[r1])/(x[r1-1] - x[r1])/2;
     29     double tmp21 = 2*d - x[l2];
     30     double tmp22 = 1;
     31     double tmp23 = y[l2] + (double)(2*d - x[l2])*(y[l2+1] - y[l2])/(x[l2+1] - x[l2])/2;
     32     double tmp24 = (double)(y[l2+1] - y[l2])/(x[l2+1] - x[l2])/2;
     33     //函数Y = (tmp11 + tmp12 * x)*(tmp13 + tmp14 * x) + (tmp21 + tmp22 * x)*(tmp23 + tmp24*x)
     34     double a = tmp12 * tmp14 + tmp22 * tmp24;
     35     double b = tmp11 * tmp14 + tmp12 * tmp13 + tmp21 * tmp24 + tmp22 * tmp23;
     36     double c = tmp11 * tmp13 + tmp21 * tmp23;
     37 
     38     double x0 = -b /(2*a);//对称轴
     39     double ret = max(a*left*left + b*left + c,a*right *right + b * right + c);
     40     if(x0 >= left && x0 <= right)
     41         ret = max(ret,a * x0 * x0 + b*x0 + c);
     42     return ret;
     43 
     44     /*
     45     double ret1,ret2;
     46     for(int cc = 0;cc <= 30;cc++)
     47     {
     48         double mid = (left + right)/2;
     49         double midmid = (mid + right)/2;
     50         double h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (mid  - x[r1])/(x[r1-1] - x[r1]);
     51         double h2 = y[l2] + (double)(y[l2+1] - y[l2])*(mid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
     52         ret1 = (double)(x[r1] - mid)*(h1 + y[r1])/2 + (double)(mid + 2*d - x[l2])*(h2 + y[l2])/2;
     53         
     54          h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (midmid  - x[r1])/(x[r1-1] - x[r1]);
     55          h2 = y[l2] + (double)(y[l2+1] - y[l2])*(midmid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
     56         ret2 = (double)(x[r1] - midmid)*(h1 + y[r1])/2 + (double)(midmid + 2*d - x[l2])*(h2 + y[l2])/2;
     57         if(ret1 < ret2)
     58             left = mid+eps;
     59         else right = midmid-eps;
     60     }
     61     return ret1;
     62     */
     63 }
     64 
     65 
     66 int input()
     67 {
     68     char ch;
     69     ch = getchar();
     70     while(ch < '0' || ch >'9')
     71     {
     72         ch = getchar();
     73     }
     74     int ret = 0;
     75     while(ch >= '0' && ch <= '9')
     76     {
     77         ret *= 10;
     78         ret += ch -'0';
     79         ch = getchar();
     80     }
     81     return ret;
     82 }
     83 
     84 int main()
     85 {
     86     //freopen("D.txt","r",stdin);
     87     //freopen("out.txt","w",stdout);
     88     int T;
     89     scanf("%d",&T);
     90     while(T--)
     91     {
     92         scanf("%d%d",&n,&L);
     93         for(int i = 1;i <= n;i++)
     94         {
     95             //x[i] = input();
     96             //y[i] = input();
     97             scanf("%d%d",&x[i],&y[i]);
     98         }
     99             //scanf("%d%d",&x[i],&y[i]);
    100         scanf("%d",&d);
    101         double ans = 0;
    102          r1 = 2;
    103          l2 = 1;
    104         double tmp = 0;
    105         while(l2 < n && x[l2+1] < 2*d)l2++;
    106         for(int i = r1;i < l2;i++)
    107         {
    108             tmp += (double)(x[i+1] - x[i])*(y[i] + y[i+1])/2;
    109         }
    110         if(l2  == 1)
    111         {
    112             tmp -= (double)(x[2] - x[1])*(y[2] + y[1])/2;
    113         }
    114         x[n+1] = x[n];
    115         y[n+1] = y[n];
    116         nowx = 0;
    117         //printf("%d %d
    ",r1,l2);
    118         while(l2 < n && r1 <= n)
    119         {
    120             int p1 = x[r1];
    121             int p2 = x[l2 + 1] - 2*d;
    122             if(p1 < p2)
    123                 nextx = p1;
    124             else nextx = p2;
    125             nextx = min(L- 2*d,nextx);
    126             //printf("%d %d
    ",nowx,nextx);
    127             ans = max(ans,tmp + solve());
    128             if(p1 < p2)
    129             {
    130                 nowx = p1;
    131                 if(r1 < n)tmp -= (double)(x[r1+1] - x[r1])*(y[r1+1] + y[r1] )/2;
    132                 r1++;
    133             }
    134             else
    135             {
    136                 nowx = p2;
    137                 tmp += (double)(x[l2+1] - x[l2])*(y[l2+1] + y[l2])/2;
    138                 l2++;
    139             }
    140         }
    141         printf("%.3lf
    ",ans/2/d);
    142     }
    143     return 0;
    144 }
  • 相关阅读:
    linux学习-----项目上线步骤
    linux学习-----数据库MySQL
    linux学习-----shell基础
    linux学习-----网络基础,网络相关命令,项目上线流程
    linux学习-----linux权限,sudo的使用
    linux学习-----开机启动项设置,ntp服务,防火墙服务,rpm服务,cron服务
    linux学习-----用户,用户组管理 网络设置 ssh服务
    linux学习-----vim编辑器的使用
    linux学习-----指令学习2 及练习
    linux学习-----指令学习1
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3506410.html
Copyright © 2020-2023  润新知