2017-10-04清北模拟赛

T1 财富(treasure)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK有n个小伙伴。每个小伙伴有一个身高hi。

这个游戏是这样的,LYK生活的环境是以身高为美的环境,因此在这里的每个人都羡慕比自己身高高的人,而每个人都有一个属性ai表示它对身高的羡慕值。

这n个小伙伴站成一列,我们用hi来表示它的身高,用ai来表示它的财富。

每个人向它的两边望去,在左边找到一个最近的比自己高的人,然后将ai朵玫瑰给那个人,在右边也找到一个最近的比自己高的人,再将ai朵玫瑰给那个人。当然如果没有比自己身高高的人就不需要赠送别人玫瑰了。也就是说一个人会给0,1,2个人玫瑰(这取决于两边是否有比自己高的人)。

每个人都会得到若干朵玫瑰(可能是0朵),LYK想知道得了最多的玫瑰的那个人得了多少玫瑰。(然后嫁给他>3<)

输入格式(treasure.in)

    第一行一个数n表示有n个人。

    接下来n行,每行两个数hi,ai。

输出格式(treasure.out)

    一个数表示答案。

输入样例

3

4 7

3 5

6 10

输出样例

12

样例解释

第一个人会收到5朵玫瑰,第二个没人送他玫瑰,第三个人会收到12朵玫瑰。

数据范围

对于50%的数据n<=1000,hi<=1000000000。

对于另外20%的数据n<=50000,hi<=10。

对于100%的数据1<=n<=50000,1<=hi<=1000000000。1<=ai<=10000。

 1 /*
 2 o(n)每个点向左找一个最近的且比它大的,
 3 o(n)每个点向右找一个最近的且比他大的
 4 f[i]第i个人收到的玫瑰数
 5 Stack[i]在单调的数列中第i个位置是n个人中的哪个人
 6 求最靠近它且比它高的那个位置是哪个
 7 O(n)
 8 */
 9 #include <cstdio>
10 
11 #define LL long long
12 inline void read(LL &x)
13 {
14     x=0; register char ch=getchar();
15     for(; ch>'9'||ch<'0'; ) ch=getchar();
16     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
17 }
18 const int N(50005);
19 LL n,h[N],v[N],f[N],ans;
20 int Stack[N],top;
21 
22 int Presist()
23 {
24 //    freopen("treasure.in","r",stdin);
25 //    freopen("treasure.out","w",stdout);
26     read(n);
27     for(int i=1; i<=n; ++i)
28         read(h[i]),read(v[i]);
29     for(int i=1; i<=n; ++i)
30     {
31         for(; top&&h[i]>=h[Stack[top]]; ) top--;
32         //=注意 
33         f[Stack[top]]+=v[i];
34         Stack[++top]=i;
35     }    top=0;
36     for(int i=n; i>=1; --i)
37     {
38         for(; top&&h[i]>=h[Stack[top]]; ) top--;
39         f[Stack[top]]+=v[i];
40         Stack[++top]=i;
41     }
42     for(int i=1; i<=n; ++i)
43         ans=ans>f[i]?ans:f[i];
44     printf("%I64d",ans); 
45     return 0;
46 }
47 
48 int Aptal=Presist();
49 int main(int argc,char**argv){;}
AC

T2 正方形(square)

Time Limit:1000ms   Memory Limit:128MB

题目描述

在一个10000*10000的二维平面上,有n颗糖果。

LYK喜欢吃糖果!并且它给自己立了规定,一定要吃其中的至少C颗糖果!

事与愿违,LYK只被允许圈出一个正方形,它只能吃在正方形里面的糖果。并且它需要支付正方形边长的价钱。

LYK为了满足自己的求食欲,它不得不花钱来圈一个正方形,但它想花的钱尽可能少,你能帮帮它吗?

输入格式(square.in)

    第一行两个数C和n。

    接下来n行,每行两个数xi,yi表示糖果的坐标。

输出格式(square.out)

    一个数表示答案。

输入样例

3 4

1 2

2 1

4 1

5 2

输出样例

4

样例解释

选择左上角在(1,1),右下角在(4,4)的正方形,边长为4。

数据范围

对于30%的数据n<=10。

对于50%的数据n<=50。

对于80%的数据n<=300。

对于100%的数据n<=1000。1<=xi,yi<=10000。

 1 /*
 2 求最小的代价,考虑二分(logmaxlen)
 3 发现数据范围支持n^2logmaxlen的复杂度
 4 现将所求正方形看做是一个无限高的矩形,
 5 O(n)枚举一个右端点,确定出左端点后,
 6 再O(n)判断在规定的高度内能否得到C个糖果 
 7 */
 8 #include <algorithm>
 9 #include <cstdio>
10 
11 inline void read(int &x)
12 {
13     x=0; register char ch=getchar();
14     for(; ch>'9'||ch<'0'; ) ch=getchar();
15     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
16 }
17 const int N(1e3+5);
18 
19 struct Pos {
20     int x,y; 
21     bool operator < (const Pos&a)const
22     {
23         return x<a.x;
24     }
25 }pos[N];
26 
27 int n,c,L,R,Mid,ans,cnt,tmp[N];
28 bool cmp(int a,int b) { return a<b; }
29 inline bool judge(int l,int r)
30 {
31     if(r-l+1<c) return false;
32     cnt=0;
33     for(int i=l; i<=r; ++i)
34         tmp[++cnt]=pos[i].y;
35     std::sort(tmp+1,tmp+cnt+1,cmp);
36     for(int i=c; i<=cnt; ++i)
37         if(tmp[i]-tmp[i-c+1]<=Mid) return 1;
38     return false;
39 }
40 inline bool check(int x)
41 {
42     int l=1,r=1;
43     for(; r<=n; ++r)
44      if(pos[r].x-pos[l].x>x)
45      {
46         if(judge(l,r-1)) return true;
47         for(; pos[r].x-pos[l].x>x; ) l++;
48      }
49     return judge(l,n);
50 }
51 
52 int Presist()
53 {
54     read(c),read(n);
55     for(int i=1; i<=n; ++i)
56         read(pos[i].x),read(pos[i].y);
57     std::sort(pos+1,pos+n+1);
58     for(R=10000; L<=R; )
59     {
60         Mid=L+R>>1;
61         if(check(Mid))
62         {
63             R=Mid-1;
64             ans=Mid+1;
65         }
66         else L=Mid+1;
67     }
68     printf("%d
",ans);
69     return 0;
70 }
71 
72 int Aptal=Presist();
73 int main(int argc,char**argv){;}
AC

T3 追逐(chase)

Time Limit:1000ms   Memory Limit:128MB

题目描述

这次,LYK以一个上帝视角在看豹子赛跑。

在一条无线长的跑道上,有n只豹子站在原点。第i只豹子将在第ti个时刻开始奔跑,它的速度是vi/时刻。

因此在不同的时刻,这n只豹子可能在不同的位置,并且它们两两之间的距离也将发生变化。

LYK觉得眼光八方太累了,因此它想找这么一个时刻,使得最远的两只豹子的距离尽可能近,当然这不能是第0时刻或者第0.01时刻。它想知道的是最迟出发的豹子出发的那一刻开始,离得最远的两只豹子在距离最小的时候这个距离是多少。

当然这个时刻不仅仅可能发生在整数时刻,也就是说可能在1.2345时刻这个距离最小。

输入格式(chase.in)

    第一行一个数n。

    接下来n行,每行两个数分别是ti和vi。

输出格式(chase.out)

    输出一个数表示答案,你只需保留小数点后两位有效数字就可以了。

输入样例

3

1 4

2 5

3 7

输出样例

0.33

样例解释

在第5+2/3这个时刻,第一只豹子在18+2/3这个位置,第二只豹子在18+1/3这个位置,第三只豹子在18+2/3这个位置,最远的两只豹子相距1/3的距离,因此答案是0.33。

数据范围

对于20%的数据n=2。

对于20%的数据n=3

对于60%的数据n<=100。

对于80%的数据n<=1000。

对于100%的数据n<=100000,1<=vi,ti<=100000。

二分+计算几何。

  1 /*
  2 左边为1的情况下,右边是什么
  3 
  4 随着左边向右移动,右边也一定向右移动。
  5 
  6 左边至多移动n次,右边也至多移动n次,总共2n次。  O(n),这个宽t至少是多少
  7 
  8 假设绿色的最短的那根不在交点处取到。
  9 t>mid  不可行   t<=mid  可行
 10 
 11 求出所有交点,然后再求每只豹子在这个交点的那个时刻的位置,更新答案。
 12 */
 13 #include<algorithm>
 14 #include<iostream>
 15 #include<cstring>
 16 #include<cstdlib>
 17 #include<cstdio>
 18 #include<cmath>
 19 
 20 using namespace std;
 21 
 22 const long double INF=(long double)1000000000*10;
 23 const int N(1e5+5);
 24 long double L,R,mid,ans,hh[N];
 25 int r,rr,i,n,MAX,X,Y,cnt,vv[N],vv2[N];
 26 struct node2 {
 27     int t;
 28     long double l;
 29 } s[N<<1],S[N<<1];
 30 struct node {
 31     int t,v;
 32 } t[N];
 33 int cmp(node i,node j)
 34 {
 35     return i.v<j.v || i.v==j.v && i.t>j.t;
 36 }
 37 struct Node
 38 {
 39     long double x;
 40     int y,z;
 41 } p[N<<1];
 42 int CMP(Node i,Node j)
 43 {
 44     return i.x<j.x;
 45 }
 46 long double work(int x,long double y)
 47 {
 48     return (long double)t[x].v*y-hh[x];
 49 }
 50 int main()
 51 {
 52     freopen("chase.in","r",stdin);
 53     freopen("chase.out","w",stdout);
 54     while (1)
 55     {
 56         scanf("%d",&n);
 57         // if (n==0) return 0;
 58         MAX=0;
 59         for (i=1; i<=n; i++)
 60         {
 61             scanf("%d%d",&t[i].t,&t[i].v);
 62             MAX=max(MAX,t[i].t);
 63         }
 64         sort(t+1,t+n+1,cmp);
 65         int MIN=t[n].t;
 66         for (i=n-1; i>=2; i--)
 67         {
 68             if (t[i].t>MIN) vv[i]=1;
 69             else
 70                 MIN=t[i].t,vv[i]=0;
 71         }
 72         for (i=1; i<=n; i++) hh[i]=(long double)t[i].t*t[i].v;
 73         r=1;
 74         s[1].l=MAX;
 75         s[1].t=1;
 76         s[2].l=INF;
 77         vv[n]=0;
 78         for (i=2; i<=n; i++)
 79             if (!vv[i])
 80             {
 81                 while (r && work(i,s[r].l)>=work(s[r].t,s[r].l)) r--;
 82                 if (!r)
 83                 {
 84                     r=1;
 85                     s[1].l=MAX;
 86                     s[1].t=i;
 87                     continue;
 88                 }
 89                 L=s[r].l;
 90                 R=s[r+1].l;
 91                 mid=(L+R)/2.0;
 92                 for (int I=1; I<=80; I++)
 93                 {
 94                     if (work(i,mid)>=work(s[r].t,mid))
 95                     {
 96                         R=mid;
 97                         mid=(L+R)/2.0;
 98                     }
 99                     else
100                     {
101                         L=mid;
102                         mid=(L+R)/2.0;
103                     }
104                 }
105                 s[++r].l=mid;
106                 s[r].t=i;
107                 s[r+1].l=INF;
108             }
109         rr=1;
110         S[1].l=MAX;
111         S[2].l=INF;
112         S[1].t=n;
113         MIN=t[1].t;
114         for (i=2; i<n; i++)
115             if (t[i].t<MIN) vv2[i]=1;
116             else
117                 MIN=t[i].t,vv2[i]=0;
118         for (i=n-1; i>=1; i--)
119             if (!vv2[i])
120             {
121                 while (rr && work(i,S[rr].l)<=work(S[rr].t,S[rr].l)) rr--;
122                 if (!rr)
123                 {
124                     rr=1;
125                     S[1].l=MAX;
126                     S[1].t=i;
127                     continue;
128                 }
129                 L=S[rr].l;
130                 R=S[rr+1].l;
131                 mid=(L+R)/2.0;
132                 for (int I=1; I<=80; I++)
133                 {
134                     if (work(i,mid)<=work(S[rr].t,mid))
135                     {
136                         R=mid;
137                         mid=(L+R)/2.0;
138                     }
139                     else
140                     {
141                         L=mid;
142                         mid=(L+R)/2.0;
143                     }
144                 }
145                 S[++rr].l=mid;
146                 S[rr].t=i;
147                 S[rr+1].l=INF;
148             }
149         cnt=0;
150         for (i=1; i<=r; i++)
151         {
152             p[++cnt].x=s[i].l;
153             p[cnt].y=1;
154             p[cnt].z=s[i].t;
155         }
156         for (i=1; i<=rr; i++)
157         {
158             p[++cnt].x=S[i].l;
159             p[cnt].y=0;
160             p[cnt].z=S[i].t;
161         }
162         sort(p+1,p+cnt+1,CMP);
163         X=Y=0;
164         ans=INF;
165         for (i=1; i<=cnt; i++)
166         {
167             if (p[i].y==1) X=p[i].z;
168             else Y=p[i].z;
169             //  printf("%.5f
",(double)p[i].x);
170             if (X && Y) ans=min(ans,work(X,p[i].x)-work(Y,p[i].x));
171         }
172         printf("%.2f
",fabs((double)ans));
173         return 0;
174     }
175 }
AC
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/7629306.html