当前位置: 首页 > news >正文

「Note」Ynoi 系列大分块

最初分块

\(\color{black}{P4119 [Ynoi2018] 未来日记}\)

主体思路:序列分块 + 值域分块

复杂度:\(O(n(\frac{n}{b} + b))\) (大约是这个级别,需要考虑两种块长)

完整思路

考虑数列分块+值域分块

数列分块需要维护:

\(nid_{i,j}\) \(fid_i\) \(f_i\)
\(i\) 中数字 \(j\) 的并查集的根 \(i\) 为根的并查集表示的数字 并查集

值域分块需要维护:

\(ncnt_{i,j}\) \(bcnt_{i,j}\)
\(i\) 个块数字 \(j\) 的出现次数 \(i\) 个块中在值域块 \(j\) 中的个数

预处理:

序列分块、值域分块块长,序列、值域每个值对应块。
每个块用 \(nid,fid\) 建立映射,\(f_i\) 连向此块与当前点值相同的第一个值(的下标),若此块中第一次出现当前点值,则考虑对 \(nid,fid\) 赋值。
显著地,扫一遍序列同时现将 \(ncnt,bcnt\) 赋上初值,再进行一遍前缀和。

修改:

碎块直接暴力赋值暴力重构,记得更新前缀和。
整块直接合并 \(x,y\) 两值,若 \(y\) 值不存在则直接将 \(x\) 并查集根节点所代表值改为 \(y\)

有一个细节,处理整块时,需要上一个块的原前缀和信息,所以要先把信息记录下来再更新上一个块的前缀和信息。最后把所有后缀的块的信息更新一下。

查询:

碎块处理需要先访问到序列真实值,考虑开两个数组维护碎块的每个值出现次数、值域块内值个数。
查询直接先一点点跳整块(要算上碎块维护的值以及整块的值),然后一个个跳数字找到答案。
查询完毕记得清空维护碎块数组,注意要用添加的镜像操作回退,保证复杂度。

$\text{Code}$:
#include<bits/stdc++.h>
using namespace std;typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned int UIT;
typedef double DB;
typedef pair<int, int> PII;
#define IL inline
#define RE register#define fi first
#define se second
//--------------------//
//IO
IL int rd() {int ret = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-')f = -f;ch = getchar();}while (ch >= '0' && ch <= '9')ret = ret * 10 + ch - '0', ch = getchar();return ret * f;
}
//--------------------//
const int N = 1e5 + 5, V = 1e5;
int n, m, a[N];
//--------------------//
const int LENA = 512, LENV = 512;
const int QNA = N / LENA + 5, QNV = V / LENV + 5;int acnt, al[N], ar[N], aid[N];
int vcnt, vid[N];int nid[QNA][N], fid[N], f[N];
int ncnt[QNA][N], bcnt[QNA][QNV];int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);
}void init_bl(int id) {for (int i = al[id]; i <= ar[id]; i++) {fid[i] = a[i], ncnt[id][a[i]]++, bcnt[id][vid[a[i]]]++;if (!nid[id][a[i]])nid[id][a[i]] = i, fid[i] = a[i];f[i] = nid[id][a[i]];// printf("f %d %d %d\n", i, f[i], nid[id][a[i]]);}return;
}void init() {for (int i = 1; i <= n; i++)aid[i] = (i - 1) / LENA + 1;acnt = aid[n];for (int i = 1; i <= acnt; i++)al[i] = (i - 1) * LENA + 1, ar[i] = i * LENA;ar[acnt] = n;for (int i = 1; i <= V; i++)vid[i] = (i - 1) / LENV + 1; vcnt = vid[V];for (int i = 1; i <= acnt; i++) {init_bl(i);for (int j = 1; j <= V; j++)ncnt[i][j] += ncnt[i - 1][j];for (int j = 1; j <= vcnt; j++)bcnt[i][j] += bcnt[i - 1][j];}
}int temp;void modify_temp(int id, int x, int y) {ncnt[id][x] -= temp, ncnt[id][y] += temp;bcnt[id][vid[x]] -= temp, bcnt[id][vid[y]] += temp;return;
}void modify_pic(int id, int l, int r, int x, int y) {if (!nid[id][x])return;for (int i = al[id]; i <= ar[id]; i++)a[i] = fid[find(i)];/*printf("MTes:\n");for (int i = al[id]; i <= ar[id]; i++)printf("%d %d\n", i, a[i]);*/for (int i = l; i <= r; i++)if (a[i] == x)temp++, a[i] = y;fid[nid[id][x]] = 0, nid[id][x] = 0;for (int i = al[id]; i <= ar[id]; i++) {if (a[i] == x) {if (!nid[id][x])nid[id][x] = i, fid[i] = x;f[i] = nid[id][x];} else if (a[i] == y) {if (!nid[id][y])nid[id][y] = i, fid[i] = y;f[i] = nid[id][y];}}return;	
}void modify_bl(int id, int x, int y) {if (!nid[id][x])return;if (!nid[id][y]) {nid[id][y] = nid[id][x];fid[nid[id][y]] = y;nid[id][x] = 0;return;}f[nid[id][x]] = nid[id][y];fid[nid[id][x]] = nid[id][x] = 0;// printf("done!\n");return;
}void modify(int l, int r, int x, int y) {temp = 0;if (aid[l] == aid[r]) {int id = aid[l];modify_pic(id, l, r, x, y);for (int i = id; i <= acnt; i++)modify_temp(i, x, y);return;}modify_pic(aid[l], l, ar[aid[l]], x, y);for (int tem, i = aid[l] + 1; i < aid[r]; i++) {modify_bl(i, x, y);tem = ncnt[i][x] - ncnt[i - 1][x];modify_temp(i - 1, x, y);temp += tem;}modify_temp(aid[r] - 1, x, y);modify_pic(aid[r], al[aid[r]], r, x, y);for (int i = aid[r]; i <= acnt; i++)modify_temp(i, x, y);return;
}int temn[N], temb[QNV];int get_ans(int k, int l, int r) {int now = 1;while (k > temb[now] + bcnt[r][now] - bcnt[l - 1][now])k -= temb[now] + bcnt[r][now] - bcnt[l - 1][now], now++;for (int i = (now - 1) * LENV + 1; i <= min(now * LENV, V); i++) {k -= temn[i] + ncnt[r][i] - ncnt[l - 1][i];if (k <= 0)return i;}return 114514;
}int query(int k, int l, int r) {int lid = aid[l], rid = aid[r], res = 19198;if (lid == rid) {for (int i = l; i <= r; i++)a[i] = fid[find(i)], temn[a[i]]++, temb[vid[a[i]]]++; // printf("?%d %d %d %d\n", i, a[i], f[i], fid[f[i]]);res = get_ans(k, 1, 0);for (int i = l; i <= r; i++)temn[a[i]]--, temb[vid[a[i]]]--;return res;}for (int i = l; i <= ar[lid]; i++)a[i] = fid[find(i)], temn[a[i]]++, temb[vid[a[i]]]++;for (int i = al[rid]; i <= r; i++)a[i] = fid[find(i)], temn[a[i]]++, temb[vid[a[i]]]++;/*printf("Qtes:\n");for (int i = l; i <= ar[lid]; i++)printf("%d(f:%d, i:%d) ", a[i], f[i], i);puts("");for (int i = al[rid]; i <= r; i++)printf("%d(f:%d, i:%d) ", a[i], f[i], i);puts("");*/res = get_ans(k, lid + 1, rid - 1);for (int i = l; i <= ar[lid]; i++)a[i] = fid[find(i)], temn[a[i]]--, temb[vid[a[i]]]--;for (int i = al[rid]; i <= r; i++)a[i] = fid[find(i)], temn[a[i]]--, temb[vid[a[i]]]--;return res;
}
//--------------------//
int main()
{n = rd(), m = rd();for (int i = 1; i <= n; i++)a[i] = rd();init();for (int op, l, r, x, y, i = 1; i <= m; i++) {op = rd(), l = rd(), r = rd(), x = rd();if (op == 1) {y = rd();if (x != y)modify(l, r, x, y);} else {printf("%d\n", query(x, l, r));}}return 0;
}
http://www.jsqmd.com/news/27413/

相关文章:

  • 2025年10月超声波清洗机厂家排行榜:阿特万与四家同行对比评价
  • 2025年10月网上兼职赚钱正规平台推荐:正规主流排行榜单全解
  • 2025年清淤挖泥船生产厂家权威推荐榜单:挖泥机/全液压绞吸式挖泥船/河道挖泥船源头厂家精选
  • 线性代数 SVD | 导数 - 详解
  • vue3+ts+vant4开发,已配置自动引入,使用closeToast组件报异常closeToast is not defined
  • 2025年深圳神秘顾客调查机构权威推荐榜单:神秘顾客研究/神秘顾客暗访/神秘顾客源头机构精选
  • [MySQL] MySQL技术大全:开发、优化与运维实战
  • 2025年10月超声波清洗机厂家推荐榜:五强对比评测与选型指南
  • 2025年10月超声波清洗机厂家推荐榜:阿特万领衔五强对比评测
  • 2025年10月网上兼职赚钱正规平台推荐:市场报告与解决方案榜
  • 2025年10月网上兼职赚钱正规平台推荐:市场报告与知名列表
  • 2025年10月超声波清洗机厂家推荐榜:五强服务网络与成本效益评测
  • 2025年10月学生平板品牌推荐榜:读书郎领衔五强对比评测
  • 2025年共板法兰机生产厂家权威推荐榜单:风管生产线/螺旋风管机/风管接料平台源头厂家精选
  • 2025年10月网上兼职赚钱正规平台推荐:排行榜单与解决方案
  • 2025年10月卖得好的学习机品牌推荐:市场销量榜与公信力排名解读
  • 2025年10月学生平板品牌推荐:投入研发榜对比教研深度
  • 2025年10月学生平板品牌对比榜:五强横评助你锁定高效学习机
  • 2025年10月学生平板品牌对比榜:读书郎与四款热门机型全解析
  • 2025年10月智能学习机品牌推荐:双师AI榜对比清北真人辅导实力
  • 2025年10月卖得好的学习机品牌推荐:用户榜真实评价与选购排行
  • 2025年10月卖得好的学习机品牌推荐:权威销量榜与品牌对比排行
  • 2025年10月卖得好的学习机品牌推荐:销量排行五强横向评测
  • zerofs 常见问题以及解决方法
  • 2025年10月智能学习机品牌推荐榜:AI学习工具数量与教研投入排行
  • 2025年10月智能学习机品牌评价榜:新课标全科覆盖机型口碑排行
  • 2025年10月智能学习机品牌推荐:新课标闭环学习方案排行
  • 2025年10月智能学习机品牌对比:新课标同步与护眼大屏选购指南
  • 日记1
  • Java 运行时安全:输入验证、沙箱机制、安全反序列化