模板【莫队】done

PART1(算法思想简介

1.实现、dalao分析

从入门到精通(优)

一般莫队的详细理解、为啥要分块 还得看这里(优)

回滚莫队

回滚莫队2 :就是把l定住,这样r就是递增的了

2.时间复杂度

3.适用情况、特别优势需要注意的点

4.函数、变量名的解释+英文

PART2(算法各种类型(并附上代码)

 题目

/**
莫队提供了这样一个排序方案:将原序列以根号下n为一块进行分块(分块的大小也珂以调整)
**/
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define N 100005
using namespace std;
inline int read() {
  register int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-')
      f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9')
    x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
  return x * f;
}
int v[N], blocksize = 0;//v:value , blocksize:分块大小
struct query {
  int l, r, id, bl;//l,r为左右区间编号,p是第几组查询的编号(记录下来为了排序后不打乱顺序还按照原查询的顺序输出),bl是分块数。
} q[N];//一个询问
int sum[N];//记录x这个数字出现过多少次了
bool ans[N];//i询问如果没有重复的赋值为true,否则为false
int cnt = 0;//记录数字的种类
inline void add(register int x) {
  if (++sum[v[x]] == 1)
    ++cnt;
}
inline void del(register int x) {
  if (--sum[v[x]] == 0)
    --cnt;
}
inline bool cmp(register query a, register query b) {
  //排序第一关键字是询问的左端点所在块的编号,第二关键字是询问的右端点本身的位置,都是升序
  //下就是一般的莫队排序
  //return a.bl==b.bl?a.r<b.r:a.bl<b.bl;
  //又多出一种优化,叫做奇偶优化
  //如果区间左端点所在块不同,那么就直接按左端点从小到大排;如果相同,奇块按右端点从小到大排,偶块按右端点从大到小排。
  return a.bl != b.bl ? a.l < b.l : ((a.bl & 1) ? a.r < b.r : a.r > b.r);
}
int main() {
  //init
  memset(sum, 0, sizeof(sum));
  //cin
  int n = read(), m = read();
  for (register int i = 1; i <= n; ++i)
    v[i] = read();
  //对询问按照分块排序
  blocksize = sqrt(n);
  for (register int i = 1; i <= m; ++i) {
    int l = read(), r = read();
    q[i] = (query){l, r, i, (l - 1) / blocksize + 1};
  }
  sort(q + 1, q + m + 1, cmp);
  //窗口式更新1~m个节点的答案
  int l = 1, r = 0;
  for (register int i = 1; i <= m; ++i) {
    int ll = q[i].l, rr = q[i].r;//目标区间
    while (l < ll)//左端点包含多了
      del(l++);
    while (l > ll)//做端点包含少了
      add(--l);
    while (r < rr)//右端点包含少了
      add(++r);
    while (r > rr)//右端点包含多了
      del(r--);
    ans[q[i].id] = (cnt == rr - ll + 1) ? 1 : 0;//求出来若区间种类数cnt == 区间长度,就ok
  }
  for (register int i = 1; i <= m; ++i)
    if (ans[i])
      puts("Yes");
    else
      puts("No");
  return 0;
}
一般莫队

 

PART3(算法的延伸应用、深度的理解、相关的有趣题目

 

posted @ 2021-07-19 15:19  bear_xin  阅读(58)  评论(0编辑  收藏  举报