1.中位数
【问题描述】
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
【文件输入】
第一行为两个正整数n和b,第二行为1~n的排列。
【文件输出】
输出一个整数,即中位数为b的连续子序列个数。
【样例输入1】
5 4
1 2 3 4 5
【样例输出1】
2
【样例输入2】
6 3
1 2 3 4 5 6 3
【样例输出2】
1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 program median;
2 var n,m,i,j,k,st,max,ans:longint;
3 a,s:array[0..100000]of longint;
4 b1,b2:array[-100000..100000,0..1]of longint;
5 begin
6 assign(input,'median.in');reset(input);
7 assign(output,'median.out');rewrite(output);
8 readln(n,m);
9 for i:=1 to n do
10 begin
11 read(a[i]);
12 if a[i]=m then st:=i;
13 end;
14 readln;
15 for i:=st-1 downto 1 do
16 begin
17 if a[i]<a[st] then begin s[i]:=s[i+1]-1;inc(b1[s[i],(st-i) mod 2]);end
18 else
19 begin
20 s[i]:=s[i+1]+1;
21 inc(b1[s[i],(st-i)mod 2]);
22 end;
23 if abs(s[i])>max then max:=abs(s[i]);
24 end;
25 for i:=st+1 to n do
26 begin
27 if a[i]<a[st] then begin s[i]:=s[i-1]-1;inc(b2[s[i],(i-st)mod 2]);end
28 else begin s[i]:=s[i-1]+1;inc(b2[s[i],(i-st)mod 2]);end;
29 if abs(s[i])>max then max:=abs(s[i]);
30 end;
31 ans:=0;
32 for i:=1 to max do
33 ans:=ans+b1[i,0]*b2[-i,0]+b1[-i,1]*b2[i,1];
34 inc(ans,b1[0,0]);
35 inc(ans,b2[0,0]);
36 inc(ans);
37 writeln(ans);
38 close(input);close(output);
39 end.
40
2.打砖块
【问题描述】
在一个凹槽中放置n层砖块,最上面的一层有n块砖,从上到下每层依次减少一块砖,每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示。14154323333376221322312311如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它;若i>1,则你必须先敲掉i-1层的第j和第j+1快砖。你现在可以敲掉最多m块砖,求得分最多能有多少。
【文件输入】
输入文件的第一行为两个正整数n和m;接下来n行,描述这n层砖块上的分值a[i][j],满足0≤a[i][j] ≤100.
【文件输出】
输出文件仅一行为一个正整数,表示被敲掉砖块的最大价值总和。
【样例输入】
4 5
2 2 3 4
8 2 7
2 3
49
【样例输出】
19
【数据规模】对于20%的数据,满足1≤n≤10,1≤m≤30;低于100%的数据,满足1≤n≤50,1≤m≤500。
dp:f[i][j][k]=max{f[i-1][j-k][p]+sum[i][k]}i表示第i列,j表示共打了j个砖块,k表示第i列打了k个砖块
sum[i][k]表示第i列打前k个砖块的和。
#include<fstream> using namespace std; ifstream cin("brike.in"); ofstream cout("brike.out"); int n,m,ans=0; int f[55][550][55]; int sum[55][55],a[55][55]; int main() { int i,j,k,l; cin>>n>>m; for (i=1;i<=n;i++) for (j=i;j<=n;j++) cin>>a[i][j]; for (j=1;j<=n;j++) for (i=1;i<=j;i++) sum[j][i]=sum[j][i-1]+a[i][j]; memset(f,255,sizeof(f)); for (j=0;j<=n;j++) f[j][0][0]=0; for (j=1;j<=n;j++) f[j][1][1]=a[1][j]; for (i=1;i<=n;i++) for (k=0;k<=i;k++) for (j=0;j<=m;j++) if (k<=j) for (l=k-1;l<i;l++) if (f[i-1][j-k][l]!=-1) { f[i][j][k]>?=f[i-1][j-k][l]+sum[i][k]; if (j==m) ans>?=f[i][j][k]; } cout<<ans<<endl; return 0; }
【问题描述】
有两个长度为N的序列A和B,在A和B中各任取一个数橡胶可以得到N2个和,求这N2个和中最小的N个。
【文件输入】
第一行输入一个正整数N;第二行N个整数Ai 且Ai≤109;第三行N个整数Bi,且Bi≤109。
【文件输出】
输出仅一行,包含n个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。
【样例输入】
5
1 3 2 4 5
6 3 4 1 7
【样例输出】
2 3 4 4 5
【数据规模】对于50%的数据,满足1≤N≤1000;对于100%的数据,满足1≤N≤100000。
维护一个小根堆。
#include<fstream> #include<cstdlib> #define maxn 100010 using namespace std; ifstream cin("sequence.in"); ofstream cout("sequence.out"); int n; int a[maxn],b[maxn],c[maxn],a0[maxn],b0[maxn]; int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; } void hsort(int l,int r) { int i=l,j; while ((i<<1)<r) { j=i*2; if (j<r&&c[j]>c[j+1])j++; if (c[i]>c[j]) {swap(c[i],c[j]);swap(a[i],a[j]);swap(b[i],b[j]);i=j;}else break; } } int main() { int i,j; cin>>n; for (i=1;i<=n;i++) cin>>a0[i]; for (i=1;i<=n;i++) cin>>b0[i]; qsort(a0+1,n,sizeof(int),cmp); qsort(b0+1,n,sizeof(int),cmp); for (i=1;i<=n;i++) { c[i]=a0[i]+b0[1]; a[i]=i; b[i]=1; } for (i=n/2;i>0;i--) hsort(i,n); for (i=1;i<=n;i++) { if (i>1) cout<<" "; cout<<c[1]; c[1]=a0[a[1]]+b0[++b[1]]; hsort(1,n); } return 0; }
【问题描述】
给出了一张有N个点M条边的加权有向无环图,接下来有Q个询问,每个询问包括2个结点X和Y,要求算出从X到Y的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)
【文件输入】
第一行包括2个整数N和M。第2到第M+1行,每行三个数字A、B、W,表示从A到B有一条权值为W的有向边。第M+2行只有一个整数Q。接下来的Q行,每行有两个整数X和Y,表示一个询问。
【文件输出】
对于每个询问输出一行,表示该询问的最小密度路径的密度(保留3位小数),如果不存在从X到Y的一条路径,则输出“OMG!”
【样例输入】
3 3
1 3 5
2 1 6
2 3 6
2
1 3
2 3
【样例输出】
5.000
5.500
【数据范围】对于60%的数据,有1≤N≤10;1≤M≤100,1≤W≤1000,1≤Q≤1000;对于100%的数据,有1≤N≤50;1≤M≤1000,1≤W≤100000,1≤Q≤100000。
floyd 开三维另一维表示两点之间有l条边
#include<cstdio> #include<cstring> int n,m,q; int a[55][55][55]={0}; int main() { freopen("path.in","r",stdin); freopen("path.out","w",stdout); int i,j,k,l; scanf("%d%d\n",&n,&m); int x,y,z; memset(a,255,sizeof(a)); for (i=1;i<=m;i++) { scanf("%d%d%d\n",&x,&y,&z); if (a[x][y][1]==-1||z<a[x][y][1]) a[x][y][1]=z; } for (i=1;i<=n;i++) a[i][i][0]=0; for (l=2;l<=n;l++) for (k=1;k<=n;k++) for (i=1;i<=n;i++) for (j=1;j<=n;j++) { if (a[i][k][l-1]>-1&&a[k][j][1]>-1&&(a[i][j][l]==-1||a[i][j][l]>a[i][k][l-1]+a[k][j][1])) a[i][j][l]=a[i][k][l-1]+a[k][j][1]; } scanf("%d\n",&q); for (i=1;i<=q;i++) { scanf("%d%d\n",&x,&y); double max=111111111; for (j=0;j<=n;j++) if (a[x][y][j]!=-1&&a[x][y][j]<max*j) max=(double)a[x][y][j]/j; if (max!=111111111) printf("%.3f\n",max);else printf("OMG!\n"); } return 0; }