KDOMINO - K-dominant array 题解
作者:互联网
【\(description\)】
这道题目意思就是先在一个给定区间中求众数出现的个数,之后再与给定的 \(k\) 相乘,比较 众数$ \times k$ 与 \(R - L + 1\) 的大小,如果前者大于等于后者,输出 \(YES\) ,否则输出 \(NO\) 。
第一行输入 \(N\) , \(Q\) ,表示数组元素的数量和操作数。
第二行输入 \(N\) 个数组元素。
第三到第 \(Q + 2\) 行,每行输入三个数 \(L\) , \(R\) ,\(K\) ,表示给定区间和要乘的数值,对于每个询问,输出 \(YES\) 或者 \(NO\)。
【\(solution\)】
吐槽一句,为啥连个数据范围都没有啊,害的我还得从 \(SPOJ\) 上找。
这里的 \(N,Q \leq 2 \times 10 ^ 5\) 。
数值应该比较大,需要离散化。(不用离散化会 \(RE\))
如何求区间众数所出现的个数 :
- 可以考虑另外开一个桶 \(tmp\) 表示出现次数为 \(x\) 的数的个数。
- 对于每次的 \(add\) ,可以先把 \(tmp[x] - 1\) ,再把 \(tmp[x + 1] + 1\)
- 对于每次的 \(del\) ,可以先把 \(tmp[x] - 1\) ,再把 \(tmp[x - 1] + 1\)
- 再用一个 \(sum\) 统计答案即可。
inline void add(int x)
{
tmp[cnt[a[x]]] -- ;
tmp[++ cnt[a[x]]] ++;
sum = max(sum,cnt[a[x]]);
return;
}
inline void del(int x)
{
tmp[cnt[a[x]]] --;
if(cnt[a[x]] == sum && tmp[cnt[a[x]]] == 0) sum --;
tmp[--cnt[a[x]]] ++;
return;
}
注意 :
用 \(cnt[x]\) 表示数值为 \(x\) 的数的个数。
-
\(add\) 没有什么问题,每次 \(sum\) 和 \(cnt[x + 1]\) 取一遍最大值即可。
-
\(del\) 时要判断 \(cnt[x] = sum\) 和 \(tmp[cnt[x]] = 0\) ,如果两个条件都满足,就表示众数的个数少了一个,\(sum - 1\) 即可。
仅满足 \(cnt[x] = sum\) ,就表示这是另为一个众数。
仅满足 \(tmp[cnt[x]] = 0\) ,表示不是众数的数的个数减少了,对答案无影响。
这里是因为莫队是一个一个数判断,所以 \(sum - 1\) 就可以代表减少后众数的数量。
之后的操作就简单了,判断 \(sum * k\) 与 \(R - L + 1\) 的大小,输出即可。
【\(Code\)】
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int Maxk = 2e5 + 10;
LL a[Maxk],b[Maxk],Ans,len,n,m;
int block,tmp[Maxk],cnt[Maxk],ans[Maxk],sum;
struct Query {
LL l,r,pos,k;
}s[Maxk];
inline LL read()
{
LL s = 0, f = 0;char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
inline bool CMP(Query a,Query b)
{
return (a.l / block) ^ (b.l / block) ? a.l / b.l : (((a.l / block) & 1) ? a.r < b.r : a.r > b.r);
}
inline void add(int x)
{
tmp[cnt[a[x]]] -- ;
tmp[++ cnt[a[x]]] ++;
sum = max(sum,cnt[a[x]]);
return;
}
inline void del(int x)
{
tmp[cnt[a[x]]] --;
if(cnt[a[x]] == sum && tmp[cnt[a[x]]] == 0) sum --;
tmp[--cnt[a[x]]] ++;
return;
}
signed main()
{
n = read(),m = read();
for(int i = 1;i <= n;i ++) a[i] = read(),b[i] = a[i];
sort(b + 1,b + n + 1);
int tot = unique(b + 1,b + 1 + n) - b - 1;
for(int i = 1;i <= n;i ++) a[i] = lower_bound(b + 1,b + 1 + tot,a[i]) - b;
block = sqrt(n);
for(int i = 1;i <= m;i ++) {
s[i].l = read();
s[i].r = read();
s[i].pos = i;
s[i].k = read();
}
sort(s + 1,s + m + 1,CMP);
int l = 1,r = 0;
for(int i = 1;i <= m;i ++) {
LL ql = s[i].l;
LL qr = s[i].r;
LL qk = s[i].k;
while(l < ql) del(l ++);
while(l > ql) add(-- l);
while(r < qr) add(++ r);
while(r > qr) del(r --);
len = qr - ql + 1;
Ans = sum * qk >= len ? 1 : 0;
ans[s[i].pos] = Ans;
}
for(int i = 1;i <= m;i ++) printf(ans[i] ? "YES\n" : "NO\n");
return 0;
}
标签:tmp,cnt,dominant,--,题解,sum,++,int,array 来源: https://www.cnblogs.com/Ti-despair/p/14473193.html