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
代码
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;
}

浙公网安备 33010602011771号