1. 程式人生 > >清北學堂D4

清北學堂D4

100% true 需要 正方 接下來 i++ part 答案 space

Part1--模擬題

今天算是正常吧,120分。其中第一題100,第二題20,第三題不知道怎麽運行時錯誤了。

(1)第一題

財富(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。

這道題從某種程度上來說是道一眼題。因為一眼就能看出O(n^2)的做法。但作為一個有追求的人,我還是認真的思考了一下有沒有O(n)的辦法,畢竟O(n^2)估計不能A。但後來也沒想出來,所以就……嗯。

我的代碼(沒想到竟然拿滿了,大概是數據有點弱):

技術分享
 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 using
namespace std; 8 long long a[50101],h[50101]; 9 long long sum[50101]; 10 int main() 11 { 12 13 freopen("treasure.in","r",stdin); 14 freopen("treasure.out","w",stdout); 15 16 int n; 17 scanf("%d",&n); 18 long long minn=1000000005,maxn=0; 19 for(int i=1;i<=n;i++) 20 { 21 scanf("%lld%lld",&h[i],&a[i]); 22 minn=min(minn,h[i]); 23 maxn=max(maxn,h[i]); 24 } 25 for(int i=1;i<=n;i++) 26 { 27 if(a[i]==maxn) continue; 28 if(a[i]==minn) {sum[i-1]+=a[i];sum[i+1]+=a[i];continue;} 29 for(int j=i-1;j>0;j--) 30 { 31 if(h[j]>h[i]) {sum[j]+=a[i];break;} 32 } 33 for(int j=i+1;j<=n;j++) 34 { 35 if(h[j]>h[i]) {sum[j]+=a[i];break;} 36 } 37 } 38 long long ans=0; 39 for(int i=1;i<=n;i++) ans=max(ans,sum[i]); 40 printf("%lld",ans); 41 //system("pause"); 42 return 0; 43 }
a

後來老師講了O(n)的做法。然而好像有點沒聽懂……代碼如下 : @周老師

技術分享
 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 int n,s[50002],d[50002],ans[50002],ANS,a[50002],b[50002],r,i;
 8 //b[i]表示第i個人收到的玫瑰數
 9 //s[]單調隊列 
10 //d[i]在單調的數列中第i個位置是n個人中的哪個人 
11 int main()
12 {
13     freopen("treasure.in","r",stdin);
14     freopen("treasure.out","w",stdout);
15     cin>>n;
16     for (i=1; i<=n; i++) scanf("%d%d",&a[i],&b[i]);
17     s[1]=a[1]; d[1]=1; r=1;
18     for (i=2; i<=n; i++)
19     {
20         while (r!=0 && a[i]>s[r]) {ans[i]+=b[d[r]]; r--; }  
21         r++;  //隊列中元素+1 
22         s[r]=a[i];//推入單調隊列 
23         d[r]=i;
24     }
25     s[1]=a[n]; d[1]=n; r=1;
26     for (i=n-1; i>=1; i--)
27     {
28         while (r!=0 && a[i]>s[r]) { ans[i]+=b[d[r]]; r--; }
29         r++;
30         s[r]=a[i];
31         d[r]=i;
32     }
33     for (i=1; i<=n; i++) ANS=max(ANS,ans[i]);
34     cout<<ANS;
35     return 0;
36 }
astd

(2)第二題

正方形(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。

我就是兩兩的枚舉端點,然後用這兩個端點擴出一個最小的正方形,之後搜一遍裏面有多少點。如果點數夠了,就與當前的ans比較,保留小的。但是只過了兩個點,其他的都結果錯誤。可能是因為我默認正方形的左上角(或右上角)有一顆糖框住,但其實不一定。

我的代碼:

技術分享
 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 using namespace std;
 8 int n,C;
 9 int xz,yz,xy,yy;
10 int maxn;
11 struct point
12 {
13     int x,y;
14     bool operator <(const point&o)const
15     {
16         if(x<o.x) return true;
17         else if(x==o.x && y<o.y) return true;
18         else return false;
19     }
20 }a[1010];
21 void make_square(int i,int j)
22 {
23     maxn=0;
24     maxn=max(abs(a[j].y-a[i].y)+1,abs(a[j].x-a[i].x)+1);
25     //cout<<maxn<<endl;
26     if(a[i].y<=a[j].y) {xz=a[i].x;yz=a[i].y;xy=xz+maxn-1;yy=yz+maxn-1;}
27     else
28     {
29         xz=a[i].x;yz=a[i].y-maxn+1;
30         xy=a[i].x+maxn-1;yy=a[i].y;
31     }
32 }
33 bool check()
34 {
35     int cnt=0;
36     for(int i=1;i<=n;i++)
37     {
38         if(a[i].x>=xz && a[i].x<=xy && a[i].y>=yz && a[i].y<=yy) cnt++;
39         if(cnt>=C) break;
40     }
41     if(cnt>=C) return true;
42     else return false;
43 }
44 
45 int main()
46 {
47     freopen("square.in","r",stdin);
48     freopen("square.out","w",stdout);
49     scanf("%d%d",&C,&n);
50     for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
51     sort(a+1,a+n+1);
52     //for(int i=1;i<=n;i++) cout<<a[i].x<<" "<<a[i].y<<endl;
53     int ans=10005;
54     for(int i=1;i<n;i++)
55     {
56         for(int j=i+1;j<=n;j++)
57         {
58             make_square(i,j);
59             if(check()) ans=min(ans,maxn);
60         }
61     }
62     printf("%d",ans);
63     //system("pause");
64     return 0;
65 }
b

正解思路:

清北學堂D4