关于noip的一道水题.....

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于noip的一道水题.....相关的知识,希望对你有一定的参考价值。

小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从
到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi。检验矿产的流程是:
1、给定 m个区间[Li,Ri];
2、选出一个参数 W;
3、对于一个区间[L,R ],计算矿石在这个区间上的检验值

Y * 1 , ] , [ i i
R L j ∈ 且 W wj
≥ ,j 是矿石编号

求解那个 ∑1 * ∑v j
j j 不明白没学过这个符号。
noip2011 day2 第2题

n
∑k

i
其中i表示下界,n表示上界, k从i开始取数,一直取到n,全部加起来。
∑ i 这样表达也可以,表示对i求和,i是变数
例如:
100
∑ i = 1+2+3+4+5+......+100
i=1
200
∑ i = 5+6+7+8+9+......+200
i=5
500
∑ i= 10+11+12+13+14+......+500
i=10
444
∑ Xi = X₁+ X₂+ X₃+ X₄+......+ X₄₄₄
i=1
50
∑ i = 1 + 2 + 3 + 4 +......+ 50 = 1275
i=1
70
∑ X = X + X + X + X +......+ X = 70X
i=1
【没有上下标时,就表示该数或该符号,重复出现】
50
∑ (n+1) = ∑n + ∑1 = 20+21+...+50 +31×1=1116
n=20
参考技术A 。。。这个就是连加符号,念作sigma

比如说∑下面写i=1,上面写n,右边写a[i],就表示i从1循环到n的a[i]之和,即a[1]+a[2]+...+a[n]

类似的有∏是连乘
参考技术B 累加的意思…… 参考技术C 是希腊字母啦 参考技术D 累加

NOIP2007统计数字

题面:

某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。

样例输入:

8
2
4
2
4
5
100
2
100

样例输出:

2 3
4 2
5 1
100 2

数据范围:N <= 200000

 

这个题因为数据范围很小,所以是一道水题,直接用sort就可以水过。时间复杂度O(nlogn)。

代码:

 

#include <stdio.h>
#include <algorithm>
int data[200010];
#define gi(a) do {                             \
  register char ch;                           while((a = getchar()) > 9 || a < 0);           for(a -= 0; (ch = getchar()) >= 0 && ch <= 9; a = a*10+ch-0); } while(0) 
int main() {
  register int i, cnt = 0, N;
  gi(N);
  for(i = 1; i <= N; i++)
    gi(data[i]);
  std::sort(data+1, data+1+N); 
  for(i = 1; i <= N; i++) {
    cnt++; 
    if(data[i] != data[i+1]) {
      printf("%d %d\n", data[i], cnt);
      cnt = 0;
    }
  }
}

实测144ms

但是如果数据卡sort(这个题数据良心不卡sort),或者N的范围更大,那么我们就要想想更好的算法了。

因为数字是固定不变的,我们首先可以想到一个很常规的算法:

开很多个桶,如果数字a出现了一次,那么桶a就++,最后把桶扫一遍。

但是如果数字太大,那么开很多个桶就会很浪费空间,甚至爆内存。

可以再开一个哈希表优化:

首先扫一遍,把值放进哈希表里,记录++。

然后把哈希表里面记录的数据扫一遍,排序输出。

设不重复的数字为m个,可见m <= n

时间复杂度O(mlogm+n*k),k取决于哈希函数的优劣(人品)

代码如下:

 

#include <stdio.h>
#include <algorithm>
#define MAXN 200010
#define gi(a) do {                             \
  register char ch;                           while((a = getchar()) > 9 || a < 0);           for(a -= 0; (ch = getchar()) >= 0 && ch <= 9; a = a*10+ch-0); } while(0)
struct number {
  int num, cnt;
};
number vis[MAXN]; 
number array[MAXN];
inline bool comp(const number &a, const number &b) {
  return a.num < b.num; 
}
inline void hash(const int &a) {
  int key = a%MAXN;
  while(vis[key].cnt && vis[key].num != a) key++;
  if(vis[key].cnt == 0) vis[key].num = a; 
  vis[key].cnt++;
}
int main() {
  int N, tot = 0, a, i, j;
  gi(N); 
  for(i = 1; i <= N; i++) {
    gi(a);
    hash(a);
  }
  for(i = 0; i <= MAXN-1; i++)
    if(vis[i].cnt)
      array[++tot] = vis[i];
  std::sort(array+1, array+tot+1, comp);
  for(i = 1; i <= tot; i++) 
    printf("%d %d\n", array[i].num, array[i].cnt);
  return 0;
}

实测64ms

(其实就这两个代码速度在所有代码中都是最快的,无论是不是加了优化)

以上是关于关于noip的一道水题.....的主要内容,如果未能解决你的问题,请参考以下文章

算法描述》关于二分的两三事

关于字符串 --java

NOIP2007统计数字

NOIP 2017 游(划水)记

历年NOIP水题泛做

关于 Noip的考纲