1. 程式人生 > >NOIP2014-6-14模擬賽

NOIP2014-6-14模擬賽

農場 return 豆豆 說明 update 兩種 ron dbf 有一個

Problem 1 抓牛(catchcow.cpp/c/pas)

【題目描述】

農夫約翰被通知,他的一只奶牛逃逸了!所以他決定,馬上出發,盡快把那只奶牛抓回來.

他們都站在數軸上.約翰在N(O≤N≤100000)處,奶牛在K(O≤K≤100000)處.約翰有兩種辦法移動,步行和瞬移:步行每秒種可以讓約翰從x處走到x+l或x-l處;而瞬移則可讓他在1秒內從x處消失,在2x處出現.然而那只逃逸的奶牛,悲劇地沒有發現自己的處境多麽糟糕,正站在那兒一動不動.

那麽,約翰需要多少時間抓住那只牛呢?

【輸入格式】

僅有兩個整數N和K

【輸出格式】

最短時間

【樣例輸入】

5 17

【樣例輸出】

4

Problem 2

路面修整(grading.cpp/c/pas)

【題目描述】

FJ打算好好修一下農場中某條凹凸不平的土路。按奶牛們的要求,修好後的路面高度應當單調上升或單調下降,也就是說,高度上升與高度下降的路段不能同時出現在修好的路中。 整條路被分成了N段,N個整數A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一個恰好含N個元素的不上升或不下降序列B_1, ... , B_N,作為修過的路中每個路段的高度。由於將每一段路墊高或挖低一個單位的花費相同,修路的總支出可以表示為: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 請你計算一下,FJ在這項工程上的最小支出是多少。FJ向你保證,這個支出不會超過2^31-1。【輸入格式】
第1行: 輸入1個整數:N * 第2..N+1行: 第i+1行為1個整數:A_i

【輸出格式】
第1行: 輸出1個正整數,表示FJ把路修成高度不上升或高度不下降的最小花費

【樣例輸入】

7
1
3
2
4
5
3
9

【樣例輸出】

3

【樣例解釋】

FJ將第一個高度為3的路段的高度減少為2,將第二個高度為3的路段的高度增加到5,總花費為|2-3|+|5-3| = 3,並且各路段的高度為一個不下降序列 1,2,2,4,5,5,9。

Problem 3 教主的魔法(magic.cpp/c/pas)

【題目描述】

教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給XMYZ信息組每個英雄看。於是N個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1、2、……、N。

每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間[L, R](1≤L≤R≤N)內的英雄的身高全部加上一個整數W。(雖然L=R時並不符合區間的書寫規範,但我們可以認為是單獨增加第L(R)個英雄的身高)

CYZ、光哥和ZJQ等人不信教主的邪,於是他們有時候會問WD閉區間 [L, R] 內有多少英雄身高大於等於C,以驗證教主的魔法是否真的有效。

WD巨懶,於是他把這個回答的任務交給了你。

【輸入格式】

第1行為兩個整數N、Q。Q為問題數與教主的施法數總和。

第2行有N個正整數,第i個數代表第i個英雄的身高。

第3到第Q+2行每行有一個操作:

(1)若第一個字母為“M”,則緊接著有三個數字L、R、W。表示對閉區間 [L, R] 內所有英雄的身高加上W。

(2)若第一個字母為“A”,則緊接著有三個數字L、R、C。詢問閉區間 [L, R] 內有多少英雄的身高大於等於C。

【輸出格式】

對每個“A”詢問輸出一行,僅含一個整數,表示閉區間 [L, R] 內身高大於等於C的英雄數。

【樣例輸入】

5 3

1 2 3 4 5

A 1 5 4

M 3 5 1

A 1 5 4

【樣例輸出】

2

3

【數據範圍】

【輸入輸出樣例說明】

原先5個英雄身高為1、2、3、4、5,此時[1, 5]間有2個英雄的身高大於等於4。教主施法後變為1、2、4、5、6,此時[1, 5]間有3個英雄的身高大於等於4。

【數據範圍】

對30%的數據,N≤1000,Q≤1000。

對100%的數據,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000

Problem 4 吃豆豆(pacman.cpp/c/pas)

【問題描述】

兩個PACMAN吃豆豆。一開始的時候,PACMAN都在坐標原點的左下方,豆豆都在右上方。PACMAN走到豆豆處就會吃掉它。PACMAN行走的路線很奇怪,只能向右走或者向上走,他們行走的路線不可以相交。

請你幫這兩個PACMAN計算一下,他們兩加起來最多能吃掉多少豆豆。

【輸入文件】

第一行為一個整數N,表示豆豆的數目。接下來N行,每行一對正整數Xi,Yi,表示第i個豆豆的坐標。任意兩個豆豆的坐標都不會重合。

【輸出文件】

僅有一行包含一個整數,即兩個PACMAN加起來最多能吃掉的豆豆數量。

【輸入樣例】

8

8 1

1 5

5 7

2 2

7 8

4 6

3 3

6 4

【輸出樣例】

7

【數據規模】

對於30%的數據,1<=N<=25;

對於70%的數據,1<=N<=500;

對於100%的數據,1<=N<=2000,1<=Xi ,Yi <=200000 ;


T1:

寬搜妥妥的,註意queue數組開3倍

技術分享
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 100005 
 6 using namespace std;
 7 int b[MAXN];
 8 int n,k;
 9 int qL[3*MAXN],qM[3*MAXN],L=1,R;
10 void bfs(){
11     qL[++R]=n;
12     qM[R]=0;
13     while(L<=R){
14         int x=qL[L],p=qM[L];
15         if(x==k){
16             return;
17         }
18         L++;
19         int dx=x+1;
20         if(0<=dx&&dx<MAXN&&!b[dx]){
21             b[dx]=p+1;
22             qL[++R]=dx;
23             qM[R]=b[dx];
24         }
25         dx=x-1;
26         if(0<=dx&&dx<MAXN&&!b[dx]){
27             b[dx]=p+1;
28             qL[++R]=dx;
29             qM[R]=b[dx];
30         }
31         dx=x*2;
32         if(0<=dx&&dx<MAXN&&!b[dx]){
33             b[dx]=p+1;
34             qL[++R]=dx;
35             qM[R]=b[dx];
36         }
37     }
38 }
39 int main()
40 {
41 //    freopen("data.in","r",stdin);
42     scanf("%d%d",&n,&k);
43     bfs();
44     printf("%d\n",b[k]);
45     return 0;
46 }
Code1

T2:

離散化+dp

將高度離散化,f[i][j]表示前i個路段解決,且最後一個路段高度為s[j]的狀態(s[j]表示從小到大排序後第j個)

則有f[1][j]=Abs(s[j]-a[1])

f[i][j]=min{f[i-1][k] | 1<=k<=j } + Abs(s[j]-a[i])

把min記錄下來邊dp邊更新O(1)

上面的方程是遞增的,遞減類似

技術分享
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 2005
 6 #define ll long long
 7 using namespace std;
 8 int a[MAXN];
 9 int s[MAXN];
10 ll f[MAXN][MAXN];
11 int n;
12 int Abs(int x){
13     return (x>0)?x:-x;
14 }
15 int read(){
16     int x=0,f=1;char ch=getchar();
17     while(ch<0||ch>9){if(-==ch)f=-1;ch=getchar();}
18     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
19     return x*f;
20 }
21 int main()
22 {
23     n=read();
24     for(int i=1;i<=n;i++){
25         s[i]=a[i]=read();
26     }
27     sort(s+1,s+n+1);
28     for(int i=1;i<=n;i++){
29         f[1][i]=Abs(s[i]-a[1]);
30     }
31     for(int i=2;i<=n;i++){
32         ll t=f[i-1][1];
33         for(int j=1;j<=n;j++){
34             t=min(t,f[i-1][j]);
35             f[i][j]=t+Abs(s[j]-a[i]);
36         }    
37     }
38     ll ans=f[n][1];
39     for(int i=2;i<=n;i++){
40         ans=min(ans,f[n][i]);
41     }
42 //    printf("%lld\n",ans);
43     for(int i=2;i<=n;i++){
44         ll t=f[i-1][n];
45         for(int j=n;j>=1;j--){
46             t=min(t,f[i-1][j]);
47             f[i][j]=t+Abs(s[j]-a[i]);
48         }    
49     }
50     for(int i=1;i<=n;i++){
51         ans=min(ans,f[n][i]);
52     }
53     printf("%lld\n",ans);
54     return 0;
55 }
Code2

T3:

平方分割

順便寫下註意事項:

1,桶中保存兩個數組,一個是原數組,一個是排序後的數組,不可搞混了

2,對於第i個元素,相應的桶編號為i/L,相應桶中的編號為i%L,前提都是從0開始計算

3,對於處理,先討論是不是在一個桶中,如果是一個桶直接L到R即可。

技術分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #define SIZE 1005
  7 #define MAXN 1000005
  8 #define ll long long
  9 using namespace std;
 10 struct Bucket{
 11     int len;
 12     ll a[SIZE];
 13     ll b[SIZE];
 14     ll tag;
 15     Bucket(){
 16         len=-1;
 17         tag=0;
 18         memset(a,0,sizeof(a));
 19         memset(b,0,sizeof(b));
 20     }
 21     void insert(ll x){
 22         a[++len]=x;
 23     }
 24     void update(){
 25         memcpy(b,a,sizeof(b));
 26         sort(b,b+len+1);
 27     }
 28     void Left_Add(int L,ll x){
 29         for(int i=L;i<=len;i++){
 30             a[i]+=x;
 31         }
 32         update();
 33     }
 34     void Right_Add(int R,ll x){
 35         for(int i=0;i<=R;i++){
 36             a[i]+=x;
 37         }
 38         update();
 39     }
 40     void Add(int L,int R,ll x){
 41         for(int i=L;i<=R;i++){
 42             a[i]+=x;
 43         }
 44         update();
 45     }
 46     void All_Add(ll x){
 47         tag+=x;
 48     }
 49     int Left_Ask(int L,ll x){
 50         x-=tag;
 51         int ret=0;
 52         for(int i=L;i<=len;i++){
 53             if(a[i]>=x){
 54                 ret++;
 55             }
 56         }
 57         return ret;
 58     }
 59     int Right_Ask(int R,ll x){
 60         x-=tag;
 61         int ret=0;
 62         for(int i=0;i<=R;i++){
 63             if(a[i]>=x){
 64                 ret++;
 65             }
 66         }
 67         return ret;
 68     }
 69     int All_Ask(ll x){
 70         x-=tag;
 71         int Pos=lower_bound(b,b+len+1,x)-b;
 72         return len-Pos+1;
 73     }
 74     int Ask(int L,int R,ll x){
 75         tag-=x;
 76         int ret=0;
 77         for(int i=L;i<=R;i++){
 78             if(a[i]>=x){
 79                 ret++;
 80             }
 81         }
 82         return ret;
 83     }
 84 }S[SIZE];
 85 ll read(){
 86     ll x=0,f=1;char ch=getchar();
 87     while(ch<0||ch>9){if(-==ch)f=-1;ch=getchar();}
 88     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 89     return x*f;
 90 }
 91 int n,L;
 92 int pos[MAXN];
 93 int main()
 94 {
 95 //    freopen("magic.in","r",stdin);
 96 //    freopen("magic.out","w",stdout);
 97     int T;
 98     scanf("%d%d",&n,&T);
 99     L=sqrt(n);
100     for(int i=0;i<n;i++){
101         ll t;
102         scanf("%lld",&t);
103         S[i/L].insert(t);
104         pos[i]=i%L;
105     }
106     for(int i=0;i<=(n-1)/L;i++){
107         S[i].update();
108     }
109     for(int i=1;i<=T;i++){
110         char ch[5];
111         int s,t;ll x;
112         scanf("%s%d%d%lld",ch,&s,&t,&x);
113         s--;t--;
114         int sx=s/L,tx=t/L;
115         if(sx!=tx){
116             if(M==ch[0]){
117                 S[sx].Left_Add(pos[s],x);
118                 S[tx].Right_Add(pos[t],x);
119                 for(int j=sx+1;j<tx;j++){
120                     S[j].All_Add(x);
121                 }
122             }    
123             else{
124                 int ans=0;
125                 ans+=S[sx].Left_Ask(pos[s],x);
126                 ans+=S[tx].Right_Ask(pos[t],x);
127                 for(int j=sx+1;j<tx;j++){
128                     ans+=S[j].All_Ask(x);
129                 }
130                 printf("%d\n",ans);
131             }        
132         }
133         else{
134             if(M==ch[0]){
135                 S[sx].Add(pos[s],pos[t],x);
136             }    
137             else{
138                 int ans=0;
139                 ans+=S[sx].Ask(pos[s],pos[t],x);
140                 printf("%d\n",ans);
141             }                
142         }
143     }
144     return 0;
145 }
Code3

T4:

先玩個dp騙騙分 40分

技術分享
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<ctime>
 6 #include<iostream>
 7 #define MAXN 205
 8 #define pii pair<int,int>
 9 using namespace std;
10 int n;
11 int X[MAXN],Y[MAXN];
12 int S[MAXN][MAXN];
13 int mx,my;
14 int dp[MAXN+MAXN][MAXN][MAXN];
15 int go[2]={0,-1};
16 pii a[MAXN];
17 void LiSan(){
18     
19     for(int i=1;i<=n;i++){
20         a[i]=make_pair(X[i],i);
21     }
22     sort(a+1,a+n+1);
23     for(int i=1;i<=n;i++){
24         if(a[i-1].first!=a[i].first) mx++;
25         X[a[i].second]=mx;
26     }
27     for(int i=1;i<=n;i++){
28         a[i]=make_pair(Y[i],i);
29     }
30     sort(a+1,a+n+1);
31     for(int i=1;i<=n;i++){
32         if(a[i-1].first!=a[i].first) my++;
33         Y[a[i].second]=my;
34     }
35 //    for(int i=1;i<=n;i++){
36 //        printf("%d %d\n",X[i],Y[i]);
37 //    }
38     for(int i=1;i<=n;i++){
39         S[X[i]][Y[i]]=1;
40     }
41 }
42 int read(){
43     int x=0,f=1;char ch=getchar();
44     while(ch<0||ch>9){if(-==ch)f=-1;ch=getchar();}
45     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
46     return x*f;
47 }
48 int main()
49 {
50 //    double begin,end;
51 //    begin=clock();
52 //    freopen("pacman1.in","r",stdin);
53 //    freopen("data.out","w",stdout);
54     n=read();
55     for(int i=1;i<=n;i++){
56         X[i]=read();
57         Y[i]=read();
58     }
59     LiSan();
60 //    for(int i=1;i<=mx;i++){
61 //        for(int j=1;j<=my;j++){
62 //            printf("%d ",S[i][j]);
63 //        }
64 //        printf("\n");
65 //    }
66     dp[3][1][2]=S[1][1]+S[1][2]+S[2][1];
67     for(int s=4;s<=mx+my-1;s++){
68         for(int i=1;i<=min(mx,s-1);i++){
69             for(int j=i+1;j<=min(mx,s-1);j++){
70                 for(int k=0;k<2;k++){
71                     int x1=i+go[k];
72                     int y1=s-1-x1;
73                     for(int l=0;l<2;l++){
74                         int x2=j+go[l];
75                         int y2=s-1-x2;
76                         if(x1==x2&&y1==y2){
77                             continue;
78                         }
79                         dp[s][i][j]=max(dp[s][i][j],dp[s-1][x1][x2]);
80                     }
81                 }
82                 dp[s][i][j]+=S[i][s-i];
83                 dp[s][i][j]+=S[j][s-j];
84             }
85         }
86     }
87     printf("%d\n",dp[mx+my-1][mx-1][mx]+S[mx][my]);
88 //    end=clock();
89 //    printf("%f\n",(end-begin)/CLOCK_PER_SEC);
90     return 0;
91 }
Code3

正解是費用流NOIP不考不管啦QAQ

NOIP2014-6-14模擬賽