2017.3.25NOIP模拟测试
1. 簡單的數(shù)列
【問題描述】
一個簡單的數(shù)列問題:
給定一個長度為 n 的數(shù)列,求數(shù)列中這樣的三個元素 ai,aj,ak 的個數(shù),滿足 ai< aj > ak,
且 i<j<k 。
【輸入】
第 1 行是一個整數(shù) n(1<=n<=50000)
。
接下來 n 行,每行一個元素 ai(0 <= ai <= 32767)。
【輸出】
一個數(shù),滿足 ai<aj>ak (i<j<k) 的個數(shù)。
【輸入輸出樣例】
Input
5
1
2
3
4
1
Output
6
【數(shù)據(jù)范圍】
對于 30%的輸入數(shù)據(jù)有 n<=2000。
對于 80%的輸入數(shù)據(jù)有 n<=10000。
對于 100%的輸入數(shù)據(jù)有 n<=50000。
?
?
第一題,樹狀數(shù)組板子題
1 #define ll long long 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime> 10 #include<cmath> 11 #include<stack> 12 #include<map> 13 #include<set> 14 15 using namespace std; 16 const int maxn=50010; 17 int C1[maxn],C2[maxn]; 18 int a[maxn],b[maxn]; 19 int c1[maxn],c2[maxn]; 20 int n; 21 void add1(int p,int x) { 22 while(p<=32768) { 23 C1[p]++; 24 p+= (p & (-p)); 25 } 26 } 27 void add2(int p,int x) { 28 while(p<=32768) { 29 C2[p]++; 30 p+=(p & (-p)); 31 } 32 } 33 int getsum1(int p) { 34 int sum=0; 35 while(p) { 36 sum+=C1[p]; 37 p-=(p & (-p)); 38 } 39 return sum; 40 } 41 int getsum2(int p) { 42 int sum=0; 43 while(p) { 44 sum += C2[p]; 45 p-=(p & (-p)); 46 } 47 return sum; 48 } 49 int main() { 50 freopen("queueb.in","r",stdin); 51 freopen("queueb.out","w",stdout); 52 cin>>n; 53 int i; 54 for(i=1; i<=n; i++) scanf("%d",&a[i]),a[i]++; 55 for(i=1; i<=n; i++) b[i]=a[n-i+1]; 56 for(i=1; i<=n; i++) { 57 add1(a[i],1); 58 int p=a[i]-1; 59 if(!p) continue; 60 c1[i]=getsum1(p); 61 } 62 for(i=1; i<=n; i++) { 63 add2(b[i],1); 64 int p=b[i]-1; 65 if(!p) continue; 66 c2[i]=getsum2(p); 67 } 68 int ll sum=0; 69 for(i=1; i<=n; i++) { 70 sum += (ll) c1[i] * (ll) c2[n-i+1]; 71 } 72 cout<<sum; 73 return 0; 74 } View Code?
- 2 -2. 黃金礦工
【問題描述】
黃金礦工是一個經(jīng)典的小游戲,它可以鍛煉人的反應(yīng)能力。該游戲中,可以通過“挖礦”
獲得積分并不斷升級。玩家可以在線玩 flash 版黃金礦工,也可以下載后玩單機(jī)版黃金礦工。
目前,黃金礦工小游戲有多個版本,例如黃金礦工雙人版,黃金礦工單人版等。
Jimmy 是一位黃金礦工,他所在的金礦是一個 n*n 的矩形區(qū)域(俯視),區(qū)域內(nèi)有黃金、
石頭和 TNT,由一個 n*n 的矩陣描述。黃金的價值對應(yīng)矩陣中的正值,石頭的價值對應(yīng)矩陣
中的負(fù)值,TNT 由 0 表示。換句話說,挖到黃金賺錢,石頭虧損,如果挖到 TNT 就掛了。
Jimmy 租到的挖礦工具很特別,它的形狀是一個長寬任意(均為正整數(shù))的矩形,可以
取走被該工具覆蓋的矩形區(qū)域內(nèi)的所有物品,但如果該區(qū)域內(nèi)有 TNT,該工具將被炸毀,此
時 Jimmy 將不得不賠償?shù)V主+∞元!!
!需要注意的是,該工具只能在金礦范圍內(nèi)使用(即不
得超出金礦邊界),且租金為每次使用十元。
現(xiàn)在,Jimmy 想知道,如果他至多只有一次租用該工具的機(jī)會,他能獲得的最大收益是
多少。當(dāng)然,如果 Jimmy 租用該工具無論如何都會虧損,他可以不租用,此時收益為 0.
【輸入】
第一行:一個整數(shù) n
接下來 n 行,每行 n 個整數(shù)(絕對值<100)
,為題目中所描述的矩陣。
【輸出】
一個數(shù),即 Jimmy 所能獲得的最大收益。
【輸入輸出樣例 1】
Input
3
0 -1 -1
0 -12 0
-19 0 0
Output
0
【樣例解釋】
無論 Jimmy 怎么挖礦,挖到的不是石頭,就是 TNT,總之無論如何都會虧損,所以選擇不租
用工具,收益為 0
【數(shù)據(jù)范圍】
對于 30%的數(shù)據(jù):0<n<=10
對于 60%的數(shù)據(jù):0<n<=100
對于 100%的數(shù)據(jù):0<n<=300
?
?
第二題,考場上沒能寫出來,。。。其實這個題要用到?jīng)Q策性優(yōu)化,如果只有一列,則最大的值這樣表示,f[i]表示以i結(jié)尾的 值最大的長條,設(shè)s[i]為前綴和,則f[i]=max(s[i]-s[k])(k<i),即找到一個最小的k,這是一個決策。那么對于i來說,i 的前面最小的也是在k的時候取得最小,是一樣的,所以i的決策就是i-1的決策,如果s[i] < s[k],則把k置為i。回到這題,只是把一維變成了二維,使用二位前綴和,相當(dāng)于還是一樣的,只要枚舉一下長度,矩陣的坐標(biāo),O(n^3);
?
1 #define ll long long 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime> 10 #include<cmath> 11 #include<stack> 12 #include<map> 13 #include<set> 14 #define SS system("pause"); 15 #define inf 3000000 16 using namespace std; 17 const int N=310; 18 int a[N][N],h[N][N]; 19 int n,ans=0; 20 void go_30() { 21 int i,j,k; 22 for(int len=1;len<=n;len++) { 23 for(i=n;i>=len;i--){ 24 k=0; 25 for(j=1;j<=n;j++){ 26 int op=h[i][k]-h[i-len][k]; 27 int now=h[i][j]-h[i-len][j]; 28 if(now<op) k=j; 29 else ans=max(ans,now-op); 30 } 31 } 32 } 33 } 34 int main() { 35 freopen("miner.in","r",stdin); 36 freopen("miner.out","w",stdout); 37 cin>>n;int i,j; 38 for(i=1;i<=n;i++) 39 for(j=1;j<=n;j++) { 40 scanf("%d",&a[i][j]); 41 if(!a[i][j]) a[i][j]=-inf; 42 h[i][j] = h[i][j-1]+a[i][j]; 43 } 44 for(i=2;i<=n;i++) 45 for(j=1;j<=n;j++) 46 h[i][j] += h[i-1][j]; 47 go_30(); 48 if(ans<=10) cout<<0; 49 else cout<<ans-10; 50 return 0; 51 } View Code?
- 3 -3. 旅行
【問題描述】
Z 小鎮(zhèn)是一個景色宜人的地方,吸引來自各地觀光客來此旅游觀光。Z 小鎮(zhèn)附近共有 N
個景點(編號為 1,2,3...N)
,這些景點被 M 條道路連接著,所有道路都是雙向的,兩個
景點之間可能有多條道路連接著。
也許是為了保護(hù)該地的旅游資源,Z 小鎮(zhèn)有個奇怪的規(guī)定,就是對于一條給定的公路
Ri,任何在該公路上行駛的車輛速度必須為 Vi。速度變化太快使得游客們很不舒服,因此
從一個景點前往另一個景點的時候,大家都希望選擇行使過程中最大速度和最小速度的比盡
可能小的路線,也就是所謂最舒適路線。
【輸入】
第一行包括兩個整數(shù): N 和 M
接下來的 M 行每行包含三個正整數(shù): x,y 和 v。表示景點 x 到景點 y 之間有一條雙向
公路,車輛必須以速度 v 在該公路上行駛。
最后一行包含兩個正整數(shù) s,t,
表示想知道從景點 s 到景點 t 最大最小速度比最小的路徑。
s 和 t 不可能相同。
【輸出】
如果景點 s 到景點 t 沒有路徑,輸出“IMPOSSIBLE”
。否則輸出一個數(shù),表示最小的速
度比。如果需要,輸出一個既約分?jǐn)?shù)。
【輸入輸出樣例 1】
Input
4
1
3
1
2
2 1
4 2
4
【輸入輸出樣例 2】
Input
3
1
1
2
1
3
2 10
2 5
3 8
3
【輸入輸出樣例 3】
Input
3
1
2
1
2
2 2
3 4
3
Output
IMPOSSIBLE
Output
5/4
Output
2
?
因為只要的到最大值與最小值的比值,能有一條路徑連通s,t即可,如果確定了最小值,只需要找到最小的最大值的邊使得s,t連通,于是把邊從小到大排序,從一到n枚舉每一條邊,設(shè)置他為最小邊,在他后面按順序加邊,直到s與t連通,得到一個比值,不斷更新答案即可;連通只要用并查集就行。
?
1 #include<algorithm> 2 #include<iostream> 3 #include<iomanip> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cstdio> 7 #include<queue> 8 #include<ctime> 9 #include<cmath> 10 #include<stack> 11 #include<map> 12 #include<set> 13 #define inf 199999999 14 #define db double 15 using namespace std; 16 const int N=510,M=5010; 17 struct E{ 18 int to,net,w; 19 int fr; 20 }e[M*2]; 21 int n,m,num_e,head[N],s,t; 22 int fa[N]; 23 void add(int x,int y,int w) { 24 e[++num_e].to=y;e[num_e].net=head[x];e[num_e].w=w;head[x]=num_e;e[num_e].fr=x; 25 } 26 int gcd(int a,int b) { 27 return a%b==0? b :gcd(b,a%b); 28 } 29 int comp(const E &a,const E &b ){ 30 return a.w<b.w; 31 } 32 void init() { 33 for(int i=1;i<=n;i++) fa[i]=i; 34 } 35 int find(int x) { 36 if(x!=fa[x]) fa[x]=find(fa[x]); 37 return fa[x]; 38 } 39 void Union(int x,int y) { 40 fa[y]=x; 41 } 42 int main() { 43 freopen("comf.in","r",stdin); 44 freopen("comf.out","w",stdout); 45 memset(head,-1,sizeof(head)); 46 cin>>n>>m;int i; 47 int a,b; 48 a=inf;b=1; 49 for(i=1;i<=m;i++) { 50 int x,y,w;scanf("%d%d%d",&x,&y,&w); 51 add(x,y,w); 52 } 53 cin>>s>>t; 54 sort(e+1,e+m+1,comp); 55 for(i=1;i<=m;i++) { 56 init();int j; 57 int minn=e[i].w; 58 for(j=i;j<=m;j++){ 59 int r1=find(e[j].fr),r2=find(e[j].to); 60 if(r1!=r2) { 61 Union(r1,r2); 62 63 } 64 // printf("%d %d\n",r1,r2); 65 if(find(s)==find(t)) break; 66 } 67 if(j>m) break; 68 if((db)e[j].w/(db)minn<(db)a/(db)b) a=e[j].w,b=minn; 69 } 70 int c=gcd(a,b); 71 a/=c,b/=c; 72 if(a==inf) { 73 puts("IMPOSSIBLE");return 0; 74 } 75 if(b==1) printf("%d",a); 76 else printf("%d/%d",a,b); 77 return 0; 78 } View Code?
【數(shù)據(jù)范圍】
0<N<=500;0<M<=5000;
- 4 -4. 奶牛跑步
【問題描述】
Bessie 準(zhǔn)備用從牛棚跑到池塘的方法來鍛煉. 但是因為她懶,她只準(zhǔn)備沿著下坡的路跑
到池塘,然后走回牛棚.
Bessie 也不想跑得太遠(yuǎn),所以她想走最短的路經(jīng). 農(nóng)場上一共有 M(1<=M<=10,000)條路,
每條路連接兩個用 1..N(1<=N<=1000)標(biāo)號的地點. 更方便的是,如果 X>Y,則地點 X 的高度大
于地點 Y 的高度. 地點 N 是 Bessie 的牛棚;地點 1 是池塘.
很快, Bessie 厭倦了一直走同一條路.所以她想走不同的路,更明確地講,她想找出
K(1<=K<=100)條不同的路經(jīng).為了避免過度勞累,她想使這 K 條路徑為最短的 K 條路徑.
請幫助 Bessie 找出這 K 條最短路經(jīng)的長度.你的程序需要讀入農(nóng)場的地圖, 一些從 Xi
到 Yi 的路徑和它們的長度(Xi,Yi,Di).
所有(Xi,Yi,Di) 滿足( 1<=Yi<Xi; Yi<Xi<=N, 1<=Di<=1,000,000 ).
【輸入】
第 1 行: 3 個數(shù): N,M,K
第 2..M+1 行: 第 i+1 行包含 3 個數(shù) Xi,Yi,Di, 表示一條下坡的路.
【輸出】
第 1..K 行: 第 i 行包含第 i 最短路徑的長度,或?1 如果這樣的路徑不存在.如果多條路徑
有同樣的長度,請注意將這些長度逐一列出.
【輸入輸出樣例】
Input
5
5
5
5
5
4
3
3
2
8
4
3
2
1
3
1
2
1
7
1
1
1
1
4
1
1
1
Output
1
2
2
3
6
7
-1
【樣例解釋】
路徑分別為(5?1),(5?3?1),(5?2?1),(5?3?2?1),(5?4?3?1),(5?4?3?2?1)
?
k短路,A*搜所,構(gòu)造反圖,處理處終點到每個點的最短距離,每次開啟隊列里dist+dis[u]最小的來擴(kuò)展,一旦擴(kuò)展到終點,就意味著找到了一條最短路,當(dāng)?shù)贙次擴(kuò)展到的時候就是第K短路。。。
?
1 #define ll long long 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime> 10 #include<cmath> 11 #include<stack> 12 #include<map> 13 #include<set> 14 using namespace std; 15 const int N=1010,M=10010; 16 struct E{ 17 int to,net,w; 18 }e[M],e2[M]; 19 int n,m,k,num_e,num; 20 int head[N],h[N]; 21 void add(int x,int y,int w) { 22 e[++num_e].to=y;e[num_e].net=head[x];e[num_e].w=w;head[x]=num_e; 23 } 24 void add2(int x,int y,int w) { 25 e2[++num].to=y;e2[num].w=w;e2[num].net=h[x];h[x]=num; 26 } 27 int dis[N],cnt[N]; 28 bool inq[N]; 29 void spfa(int s,int t) { 30 queue<int> q; 31 q.push(s); 32 inq[s]=1; 33 memset(dis,0x3f,sizeof(dis)); 34 dis[s]=0; 35 while(!q.empty()) { 36 int u=q.front();q.pop(); 37 inq[u]=0;//不加會萎 38 for(int i=h[u];i;i=e2[i].net) { 39 int to=e2[i].to; 40 if(dis[to]>dis[u]+e2[i].w) { 41 dis[to]=dis[u]+e2[i].w; 42 if(!inq[to]) q.push(to),inq[to]=1; 43 } 44 } 45 } 46 } 47 struct Node{ 48 int id,dist; 49 bool operator<(const Node & b)const{ 50 return dist + dis[id] > b.dist +dis[b.id]; 51 } 52 };//Yinpengzhe200104234532 53 void a_star(int s,int t) { 54 priority_queue<Node> q; 55 Node tmp={s,0},tt; 56 q.push(tmp); 57 while(!q.empty()) { 58 tmp=q.top();q.pop(); 59 cnt[tmp.id]++; 60 if(tmp.id==t) { 61 printf("%d\n",tmp.dist); 62 if(cnt[tmp.id]==k) return; 63 } 64 if(cnt[tmp.id]>k) continue; 65 for(int i=head[tmp.id];i;i=e[i].net) { 66 int to=e[i].to; 67 tt=(Node){to,tmp.dist+e[i].w}; 68 q.push(tt); 69 } 70 } 71 } 72 int main() { 73 freopen("cowjog.in","r",stdin); 74 freopen("cowjog.out","w",stdout); 75 cin>>n>>m>>k;int i; 76 for(i=1;i<=m;i++) { 77 int x,y,w; 78 scanf("%d%d%d",&x,&y,&w); 79 add(x,y,w);add2(y,x,w); 80 } 81 spfa(1,n); 82 a_star(n,1); 83 while(cnt[1]<k) puts("-1"),cnt[1]++; 84 return 0; 85 } View Code。。。。。。
?
轉(zhuǎn)載于:https://www.cnblogs.com/ypz999/p/flow.html
總結(jié)
以上是生活随笔為你收集整理的2017.3.25NOIP模拟测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全国主要城市空气质量热点图
- 下一篇: OpenLayer学习之OGC数据