lahlahblog喵~

luogu P4119 [Ynoi2018] 未来日记

lahlah·2022-02-22 20:10·64 次阅读

luogu P4119 [Ynoi2018] 未来日记

https://www.luogu.com.cn/problem/P4119

第一次感觉自己代码写得好优美,吹爆(bushi)

直接考虑最暴力的分块,序列分块+值域分块

bcnt[i][j]表示前i块,值域在第j块的有几个

cnt[i][j]表示前i块,值域为j的有多少个

然后查询就可以直接暴力找出位于那一值域块里(用bcnt),然后再一个个暴力找(用cnt

散块暴力重构即可

考虑修改,散块暴力修改,对于整块,如果x,y都有可以直接暴力把整个块扫一遍,把x全部改成y, 因为每次修改必定会使得其中一种消失,均摊下来是正确的(增多的情况也最多只会把两块的种类增多一个)

否则对于这块如果y不存在的话直接把y的编号设为x的编号,然后把x的删掉即可

具体实现可以参考代码,保证看得懂!!1

code:

Copy
#include<bits/stdc++.h> #define blo 320 #define N 100050 #define M 325 #define L(x) ((x - 1) * blo + 1) #define R(x) (min(x * blo, n)) using namespace std; inline int rd() { int x = 0; char ch = getchar(); for(; ch < '0' || ch > '9' ;) ch = getchar(); for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x << 1) + (ch - '0'), ch = getchar(); return x; } int lim = 100000; int a[N], b[N], cnt[M][N], bcnt[M][M], ys[M][blo + 5], bh[M][N], bel[N], n, q, m, bm; void pushdown(int id) { for(int i = L(id); i <= R(id); i ++) a[i] = ys[id][b[i]]; } void change(int id, int x, int y) { int o = bh[id][x]; bh[id][y] = o; ys[id][o] = y; bh[id][x] = 0; } void build(int id) { int gs = 0; for(int i = 1; i <= blo; i ++) bh[id][ys[id][i]] = 0; for(int i = L(id); i <= R(id); i ++) { if(!bh[id][a[i]]) { bh[id][a[i]] = ++ gs; ys[id][gs] = a[i]; } } for(int i = L(id); i <= R(id); i ++) b[i] = bh[id][a[i]]; } void init() { for(int i = 1; i <= lim; i ++) bel[i] = (i - 1) / blo + 1; m = bel[n]; bm = bel[lim]; for(int i = 1; i <= n; i ++) { int id = bel[i]; cnt[id][a[i]] ++; bcnt[id][bel[a[i]]] ++; } for(int i = 1; i <= m; i ++) { build(i); for(int j = 1; j <= lim; j ++) cnt[i][j] += cnt[i - 1][j]; for(int j = 1; j <= bm; j ++) bcnt[i][j] += bcnt[i - 1][j]; } } void chan(int l, int r, int x, int y) { if(x == y) return ; int bl = bel[l], br = bel[r]; int bx = bel[x], by = bel[y]; if(cnt[br][x] - cnt[bl - 1][x] == 0) return ; int f = 0; if(bx == by) f = 1; for(int i = m; i > 1; i --) { cnt[i][x] -= cnt[i - 1][x]; cnt[i][y] -= cnt[i - 1][y]; if(!f) bcnt[i][bx] -= bcnt[i - 1][bx], bcnt[i][by] -= bcnt[i - 1][by]; } if(bl == br) { pushdown(bl); for(int i = l; i <= r; i ++) { if(a[i] == x) { a[i] = y; cnt[bl][x] --, cnt[bl][y] ++; if(!f) bcnt[bl][bx] --, bcnt[bl][by] ++; } } build(bl); } else { pushdown(bl), pushdown(br); for(int i = l; i <= R(bl); i ++) { if(a[i] == x) { a[i] = y; cnt[bl][x] --, cnt[bl][y] ++; if(!f) bcnt[bl][bx] --, bcnt[bl][by] ++; } } for(int i = L(br); i <= r; i ++) { if(a[i] == x) { a[i] = y; cnt[br][x] --, cnt[br][y] ++; if(!f) bcnt[br][bx] --, bcnt[br][by] ++; } } build(bl), build(br); for(int i = bl + 1; i < br; i ++) { if(cnt[i][x]) { if(cnt[i][y]) { pushdown(i); for(int j = L(i); j <= R(i); j ++) { if(a[j] == x) { a[j] = y; cnt[i][x] --, cnt[i][y] ++; if(!f) bcnt[i][bx] --, bcnt[i][by] ++; } } build(i); } else { if(!f) bcnt[i][by] += cnt[i][x], bcnt[i][bx] -= cnt[i][x]; cnt[i][y] += cnt[i][x], cnt[i][x] = 0; change(i, x, y); } } } } for(int i = 2; i <= m; i ++) { cnt[i][x] += cnt[i - 1][x]; cnt[i][y] += cnt[i - 1][y]; if(!f) bcnt[i][bx] += bcnt[i - 1][bx], bcnt[i][by] += bcnt[i - 1][by]; } } int ls[N], lss[N]; void query(int l, int r, int k) { int bl = bel[l], br = bel[r]; if(bl == br) { pushdown(bl); for(int i = l; i <= r; i ++) ls[i] = a[i]; nth_element(ls + l, ls + l + k - 1, ls + r + 1); printf("%d\n", ls[l + k - 1]); for(int i = l; i <= r; i ++) ls[i] = 0; } else { pushdown(bl), pushdown(br); for(int i = l; i <= R(bl); i ++) { ls[a[i]] ++; lss[bel[a[i]]] ++; } for(int i = L(br); i <= r; i ++) { ls[a[i]] ++; lss[bel[a[i]]] ++; } // printf("** %d %d %d %d %d %d %d\n", l, r, k, bl, br, R(bl), L(br)); // for(int i = 1; i <= n; i ++) printf("%d ", ls[i]); printf("\n"); // for(int i = 1; i <= n; i ++) printf("%d ", lss[i]); printf("\n"); int s = 0, ff = 0; for(int i = 1; i <= bm; i ++) if(! ff) { if(s + lss[i] + bcnt[br - 1][i] - bcnt[bl][i] >= k) { //printf("*%d %d %d\n", i, (bel[i] - 1) * blo + 1, bel[i] * blo); for(int j = (i - 1) * blo + 1; j <= min(i * blo, lim); j ++) { if(s + ls[j] + cnt[br - 1][j] - cnt[bl][j] >= k) { printf("%d\n", j); ff = 1; break; } else s += ls[j] + cnt[br - 1][j] - cnt[bl][j]; } if(ff) break; } else s += lss[i] + bcnt[br - 1][i] - bcnt[bl][i]; } for(int i = l; i <= R(bl); i ++) { ls[a[i]] = 0; lss[bel[a[i]]] = 0; } for(int i = L(br); i <= r; i ++) { ls[a[i]] = 0; lss[bel[a[i]]] = 0; } } } int main() { //freopen("a.out","w",stdout); n = rd(), q = rd(); for(int i = 1; i <= n; i ++) a[i] = rd(); init(); // printf("\n"); // for(int i = 1; i <= n; i ++) printf(" %d ", bel[i]); printf("\n"); // for(int i = 1; i <= n; i ++) printf(" %d ", b[i]); printf("\n"); while(q --) { int o, l, r, x, y; o = rd(); if(o == 1) { l = rd(), r = rd(), x = rd(), y = rd(); chan(l, r, x, y); } else { l = rd(), r = rd(), x = rd(); query(l, r, x); } } return 0; } /* 10 5 1 2 3 3 5 6 7 8 9 10 2 3 5 2 1 3 7 3 7 1 3 7 7 3 2 3 10 4 2 3 10 3 */
posted @   lahlah  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示