NOIP2014-6-14模擬賽
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
【題目描述】
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模擬賽