现在的位置: 首页 > 综合 > 正文

【11/2】模拟赛

2012年08月23日 ⁄ 综合 ⁄ 共 4647字 ⁄ 字号 评论关闭

第一题 中位数

【题目描述】

给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。

 

【输入格式】

第一行为两个正整数n和b,第二行为1~n的排列。

 

【输出格式】

输出一个整数,即中位数为b的连续子序列个数。

 

【样例输入】

样例输入1 样例输入2 样例输入3
5 4
1 2 3 4 5
6 3
1 2 4 5 6 3
7 4
5 7 2 4 3 1 6

 

【样例输出】

样例输出1 样例输出2 样例输出3
2 1 4

 

【数据范围】

n<=100000。

 

【分析】

假设b左面有x1个比b大,y1个比b小。b右面有x2个比b打,y2个比b小。那么有x1 + x2 = y1 + y2。移项有,x1 – y1 = – (x2 – y2)。我们先统计b左面每个位置计算出的每个x - y的差值各出现了多少次,然后统计b右面的每个位置计算出的-(x – y)的差值各出现了多少次。由乘法原理将对应的相乘。

 

第二题 打砖块

【题目描述】

在一个凹槽中放置n层砖块,最上面的一层有n块砖,从上到下每层依次减少一块砖,每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示。

捕获

 

如果你要敲掉第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。

 

【分析】

首先按照正常的思想,我们会想到以行划分阶段。但是他是有后效性的。于是我们尝试用列划分阶段。

123

对于上图橘黄色的点。如果取了他,那么粉色的点都会被取走。设f[i][j][k]表示当前是第i列,共取走j个,其中k个在第i列。f[i][j][k] = max(f[i – 1][j – k][p]) + s[i][k]。其中k – 1 <= p < i(即图中有棕色点的范围),s[i][k]表示第i列最上面k个数的和。

结果为所有f[i][m][k]中最大的。

 

第三题 序列合并

【题目描述】

有两个长度为N的序列A和B,在A和B中各任取一个数相加可以得到N^2个和,求这N^2个和中最小的N个。

 

【输入格式】

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,且Bi≤10^9。

 

【输出格式】

输出仅一行,包含n个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。

 

【样例输入】

5

1 3 2 4 5
6 3 4 1 7

 

【样例输出】

2 3 4 4 5

 

【分析】

首先将两个数列排序。第一步固定b中选的数是b[1],和a中所有的数相加,得出n个数,放入小根堆中。

每次从中取出最小的。将他所选的b[i]下表加1,即变成b[i + 1]。然后放回堆中。

 

第四题 最小密度路径

【题目描述】

给出了一张有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。

 
【分析】

f[i][j][k]表示从i到j走k条边做能达到的最小值。然后floyd求解。o(n^4)。

给出的数据有误,存在环。

 

代码

第一题

 

#include <stdio.h>
#define MAXN 100010
#define pz 150000
int n,b;
int a[MAXN],f[3 * MAXN],g[3 * MAXN];
int main() {
  freopen("median.in","r",stdin);
  freopen("median.out","w",stdout);
  scanf("%d%d",&n,&b);
  for (int i = 1;i <= n;++i)
    scanf("%d",&a[i]);
  int wh,sum,ans;
  for (int i = 1;i <= n;++i)
    if (a[i] == b) {
      wh = i;
      break;
    }
  sum = 0;
  ++g[pz];
  ++f[pz];
  for (int i = wh - 1;i >0;--i) {
    if (a[i] > b)
      ++sum;
    else
      --sum;
    ++f[sum + pz];
  }
  sum = 0;
  for (int i = wh + 1;i <= n;++i) {
    if (a[i] < b)
      ++sum;
    else
      --sum;
    ++g[sum + pz];
  }
  ans = 0;
  for (int i = -n;i <= n;++i)
    ans += f[i + pz] * g[i + pz];
  printf("%d\n",ans);
  return 0;
}

 

第二题

 

#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAXN 60
#define MAXM 510
using namespace std;
int f[MAXN][MAXM][MAXM],a[MAXN][MAXN],s[MAXN][MAXN];
int n,m,ans;
int main() {
  freopen("brike.in","r",stdin);
  freopen("brike.out","w",stdout);
  scanf("%d%d",&n,&m);
  for (int i = 1;i <= n;++i)
    for (int j = 1;j <= n - i + 1;++j)
      scanf("%d",&a[i][j]);
  for (int i = 1;i <= n;++i)
    for (int j = 1;j <= i;++j)
      s[i][j] = s[i][j - 1] + a[j][n - i + 1];
  memset(f,255,sizeof(f));
  for (int i = 0;i <= n;++i)
    f[i][0][0] = 0;
  for (int i = 1;i <= n;++i)
    f[i][1][1] = a[1][n - i + 1];
  for (int i = 1;i <= n;++i)
    for (int k = 0;k <= i;++k)
      for (int j = k;j <= m;++j)
        for (int p = k - 1;p < i;++p)
          if ((p >= 0) && (f[i - 1][j - k][p] != -1)) {
            f[i][j][k] = max(f[i][j][k],f[i - 1][j - k][p] + s[i][k]);
            if ((j == m) && (f[i][j][k] > ans))
              ans = f[i][j][k];
          }
  printf("%d\n",ans);
  return 0;
}

 

第三题

 

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define MAXN 100010
using namespace std;
struct ss {
  int pa,pb,t;
} h[MAXN];
int tot,n,ans;
int a[MAXN],b[MAXN];
int cmp(const void *a,const void *b) {
  int c = *(int *)a,d = *(int *)b;
  return c - d;
}
void down(int x ) {
  int p,q;
  p = x;
  q = x * 2;
  while (q <= tot) {
    if ((q + 1 <= tot) && (h[q + 1].t < h[q].t))
      ++q;
    if (h[q].t > h[p].t)
      return;
    swap(h[q],h[p]);
    p = q;
    q = p * 2;
  }
}
int main() {
  freopen("sequence.in","r",stdin);
  freopen("sequence.out","w",stdout);
  scanf("%d",&n);
  for (int i = 1;i <= n;++i)
    scanf("%d",&a[i]);
  for (int j = 1;j <= n;++j)
    scanf("%d",&b[j]);
  qsort(a + 1,n,sizeof(int),cmp);
  qsort(b + 1,n,sizeof(int),cmp);
  for (int i = 1;i <= n;++i) {
    h[i].pa = i;
    h[i].pb = 1;
    h[i].t = a[i] + b[1];
  }
  tot = n;
  for (int i = tot;i > 0;--i)
    down(i);
  for (int i = 1;i <= n;++i) {
    ans = h[1].t;
    printf("%d ",ans);
    ++h[1].pb;
    h[1].t = a[h[1].pa] + b[h[1].pb];
    down(1);
  }
  return 0;
}

 

第四题

 

#include <stdio.h>
#define MAXINT 10000010
int n,m,x,y,z,tot;
double f[51][51][501],dis[51][51];
int main() {
  freopen("path.in","r",stdin);
  freopen("path.out","w",stdout);
  scanf("%d%d",&n,&m);
  for (int i = 1;i <= n;++i)
    for (int j = 1;j <= n;++j)
      for (int k = 0;k <= n;++k)
        f[i][j][k] = MAXINT;
  for (int i = 1;i <= m;++i) {
    scanf("%d%d%d",&x,&y,&z);
    if (z < f[x][y][1])
      f[x][y][1] = z;
  }
  for (int p = 2;p <= n;++p)
    for (int k = 1;k <= n;++k)
      for (int i = 1;i <= n;++i)
        for (int j = 1;j <= n;++j)
          if (f[i][k][p - 1] + f[k][j][1] < f[i][j][p])
            f[i][j][p] = f[i][k][p - 1] +f[k][j][1];
  scanf("%d",&tot);
  for (int i = 1;i <= n;++i)
    for (int j = 1;j <= n;++j)
      dis[i][j] = MAXINT;
  for (int i = 1;i <= n;++i)
    for (int j = 1;j <= n;++j)
      for (int k = 1;k <= n;++k)
        if (f[i][j][k] < MAXINT)
        if (f[i][j][k] / k < dis[i][j])
          dis[i][j] = f[i][j][k] / k;
  for (int i = 1;i <= tot;++i) {
    scanf("%d%d",&x,&y);
    if (dis[x][y] < MAXINT)
      printf("%.3lf\n",dis[x][y]);
    else
      printf("OMG!\n");
  }
  return 0;
}

 

 

后记

今天的题目写的很悲剧。因为身体感觉很差吧。放假调整一下,下午去买点感冒药。太冷了。

第二题打出了数组观察结果交题的时候忘记删掉了。第四题没有判断动归数组是否有解就直接去计算dis。两百分消失。

抱歉!评论已关闭.