其他分享
首页 > 其他分享> > KDOMINO - K-dominant array 题解

KDOMINO - K-dominant array 题解

作者:互联网

【\(description\)】

Link

这道题目意思就是先在一个给定区间中求众数出现的个数,之后再与给定的 \(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\))

如何求区间众数所出现的个数 :

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\) 的数的个数。

仅满足 \(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