[ZJb417]区间众数

题目大意:
  给定一个长度为$n(1\leq n\leq10^5)$的正整数序列$s(1\leq s_i\leq n)$,对于$m(1\leq m\leq10^)$次询问$l,r$,每次求区间$[s_l,\ldots,s_r]$中,众数出现的次数以及众数的个数。

思路:
  莫队。
  对于询问$l,r$,维护每个数$s_i$出现的次数$cnt1[i]$以及每个$cnt1[i]$出现的次数$cnt2[i]$。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<algorithm> 
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=100001,M=1000000;
13 int a[N],belong[M],cnt1[N],cnt2[N],tmp,ans1[M],ans2[M];
14 struct Query {
15     int l,r,id;
16     bool operator < (const Query &another) const {
17         if(belong[l]==belong[another.l]) return belong[r]<belong[another.r];
18         return belong[l]<belong[another.l];
19     }
20 };
21 Query q[M];
22 inline void ins(const int &x) {
23     cnt2[cnt1[a[x]]++]--;
24     cnt2[cnt1[a[x]]]++;
25     tmp=std::max(tmp,cnt1[a[x]]);
26 }
27 inline void del(const int &x) {
28     cnt2[cnt1[a[x]]--]--;
29     cnt2[cnt1[a[x]]]++;
30     while(!cnt2[tmp]) tmp--;
31 }
32 int main() {
33     const int n=getint(),m=getint(),block=sqrt(n);
34     for(register int i=1;i<=n;i++) {
35         a[i]=getint();
36         belong[i]=i/block;
37     }
38     for(register int i=0;i<m;i++) {
39         const int l=getint(),r=getint();
40         q[i]=(Query){l,r,i};
41     }
42     std::sort(&q[0],&q[m]);
43     for(register int i=0,l=1,r=0;i<m;i++) {
44         while(l<q[i].l) del(l++);
45         while(l>q[i].l) ins(--l);
46         while(r<q[i].r) ins(++r);
47         while(r>q[i].r) del(r--);
48         ans1[q[i].id]=tmp;
49         ans2[q[i].id]=cnt2[tmp];
50     }
51     for(register int i=0;i<m;i++) {
52         printf("%d %d\n",ans1[i],ans2[i]);
53     }
54     return 0;
55 }

 

posted @ 2018-02-06 17:44  skylee03  阅读(144)  评论(0编辑  收藏  举报