ACdream 1108(莫队)

题目链接

The kth number

Time Limit: 12000/6000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others)
Problem Description

Do you still remember the Daming Lake's  k'th number? Let me take you back and recall that wonderful memory.

Given a sequence A with length of n,and m querys.Every query is defined by three integer(l,r,k).For each query,please find the kth biggest frequency in interval [l,r].
Frequency of a number x in [l,r] can be defined by this code:

1
2
3
4
5
6
int FrequencyOfX = 0;
for ( int i = l; i <= r; i ++) {
      if (a[i]==X) {
          FrequencyOfX ++;
      }
}
Input

First line is a integer T,the test cases.
For each case:
First line contains two integers n and m.
Second line contains n integers a1,a2,a3....an.
Then next m lines,each line contain three integers l,r,k.

T<=12
1<=n,m,ai<=100000
1<=l<=r<=n
1<=k
data promise that for each query(l,r,k),the kind of number in interval [l,r] is at least k.

Output
for every query,output a integer in a line.
Sample Input
1
6 3
13 14 15 13 14 13
1 6 3
1 6 1
3 5 2
Sample Output
1
3
1
Source
zhangmingming
Manager
初次接触莫队算法。屠了一次版。。。哈哈,不要在意这些细节
和平方分割的方法类似,莫队算法的思想大概也是把线性的序列尽量平均的进行分割。
一般用于不需要队数据进行修改的题目,而且必须离线。
这里的排序,都是先按照桶的顺序升序排序,如果桶的顺序相同再按终点排序。
Accepted Code:
 1 /*
 2 * this code is made by Stomach_ache
 3 * Problem: 1108
 4 * Verdict: Accepted
 5 * Submission Date: 2014-09-04 21:32:52
 6 * Time: 1320MS
 7 * Memory: 4248KB
 8 */
 9 #include <stdio.h>
10 #include <string.h>
11 #include <algorithm>
12 using namespace std;
13 /*Let's fight!!!*/
14   
15 const int Sqrt = 333;
16 const int MAX_N = 101000;
17 int a[MAX_N], ans[MAX_N], freq[MAX_N], cnt[MAX_N];
18 int ll[MAX_N], rr[MAX_N], kk[MAX_N], idx[MAX_N], n, m;
19   
20 bool cmp (int a, int b) {
21     if (ll[a]/Sqrt == ll[b]/Sqrt) return rr[a] < rr[b];
22     return ll[a] < ll[b];
23 }
24   
25 int query(int k) {
26     int lb = 1, ub = 100001;
27     while (ub - lb > 1) {
28         int mid = (lb + ub) / 2;
29         if (freq[mid] >= k) lb = mid;
30         else ub = mid;
31     }
32     return lb;
33 }
34   
35 int main() {
36     int T;
37     scanf("%d", &T);
38     while (T--) {
39         scanf("%d%d", &n, &m);
40         for (int i = 0; i < n; i++) scanf("%d", a+i);
41         for (int i = 0; i < m; i++) {
42             scanf("%d%d%d", ll+i, rr+i, kk+i);
43             idx[i] = i; ll[i]--; rr[i]--;
44         }
45   
46         sort(idx, idx + m, cmp);
47         memset(freq, 0, sizeof(freq));
48         memset(cnt, 0, sizeof(cnt));
49   
50         int cl = 0, cr = -1;
51         for (int i = 0; i < m; i++) {
52             int l = ll[idx[i]], r = rr[idx[i]], k = kk[idx[i]];
53             while (cr < r) { freq[++cnt[a[++cr]]] ++; }
54             while (l < cl) { freq[++cnt[a[--cl]]] ++; }
55             while (r < cr) { freq[cnt[a[cr--]]--] --; }
56             while (cl < l) { freq[cnt[a[cl++]]--] --; }
57             ans[idx[i]] = query(k);
58         }
59   
60         for (int i = 0; i < m; i++) printf("%d\n", ans[i]);
61     }
62   
63     return 0;
64 }

 

转载于:https://www.cnblogs.com/Stomach-ache/p/3956935.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值