洛谷 P5355【根号分治】【莫队】

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;
struct Node {
  int opt, l, r, x, id;
} q[N];
int a[N], belong[N];
int cnt[N];
bitset <N> f, g;
bool ans[N];
int lst[N], mx[N];
vector <Node> q_[N];
int tot = 0;

void add(int x) {
  cnt[x] ++;
  if (cnt[x] == 1)
    f[x] = g[100000 - x] = 1;
}

void del(int x) {
  cnt[x] --;
  if (cnt[x] == 0)
    f[x] = g[100000 - x] = 0;
}

bool cmp(const Node &lhs, const Node &rhs) {
  if (belong[lhs.l] == belong[rhs.l])
    return lhs.r < rhs.r;
  return lhs.l < rhs.l;
}

signed main() {
  int n, m;
  cin >> n >> m;
  int block = sqrt(n);
  for (int i = 1; i <= n; i ++)
    cin >> a[i];
  for (int i = 1; i <= n; i ++)
    belong[i] = i / block + 1;
  for (int i = 1; i <= m; i ++) {
    int opt, l, r, x;
    cin >> opt >> l >> r >> x;
    if (opt == 4 && x <= 316)
      q_[x].push_back({opt, l, r, x, i});
    else {
      tot ++;
      q[tot].opt = opt, q[tot].l = l, q[tot].r = r, q[tot].x = x, q[tot].id = i;
    }
  }
  // for (int i = 1; i <= m; i ++)
  //   q[i].id = i;
  for (int i = 1; i <= 316; i ++) {
    memset (lst, 0, sizeof lst);
    memset (mx, 0, sizeof mx);
    if (q_[i].size()) for (int j = 1, p = 0; j <= n; j ++) {
      lst[a[j]] = j;
      if (a[j] % i == 0)
        p = max(p, lst[a[j] / i]);
      if (i * a[j] <= 100000)
        p = max(p, lst[i * a[j]]);
      mx[j] = p;
    }
    for (auto &j : q_[i])
      if (j.l <= mx[j.r])
        ans[j.id] = true;
  }
  sort (q + 1, q + tot + 1, cmp);
  int l = 1, r = 0;
  for (int i = 1; i <= tot; i ++) {
    while (l < q[i].l)
      del(a[l]), l ++;
    while (l > q[i].l)
      add(a[l - 1]), l --;
    while (r < q[i].r)
      add(a[r + 1]), r ++;
    while (r > q[i].r)
      del(a[r]), r --;
    int opt = q[i].opt;
    int x = q[i].x;
    if (opt == 1) {
      if ((f & (f << x)).any())
        ans[q[i].id] = true;
    } else if (opt == 2) {
      if ((f & (g >> (100000 - x))).any())
        ans[q[i].id] = true;
    } else if (opt == 3) {
      for (int j = 1; j * j <= x; j ++) {
        if (x % j)
          continue;
        if (f[j] && f[x / j]) {
          ans[q[i].id] = true;
          break;
        }
      }
    } else {
      for (int j = 1; j * x <= 100000; j ++)
        if (f[j] && f[j * x]) {
          ans[q[i].id] = true;
          break;
        }
    }
  }
  for (int i = 1; i <= m; i ++)
    if (ans[i])
      cout << "yuno\n";
    else
      cout << "yumi\n";
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值