日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

COGS-257-动态排名系统-树状数组+主席树

發布時間:2025/3/15 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 COGS-257-动态排名系统-树状数组+主席树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

描述

  • 給定一個長度為N的已知序列A[i](1<=i<=N),要求維護這個序列,能夠支持以下兩種操作:
  • 1、查詢A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的數。
  • 2、修改A[i]的值為j。
分析
  • 用了很長時間理解樹狀數組+主席樹的做法
  • 這里先有一個正常的主席樹, 保存無修改時的數據, 然后用樹狀數組維護一個記錄增量的主席樹, 維護的信息和普通樹狀數組一樣, 也是是某一段內的數據. 比如修改了位置x的數據, 那么需要更新 x, x+lowbit(x)... 直到剛小于n 的數據
#include #include #include #include using namespace std;const int maxnode = 3000000; const int maxn = 60000 + 10; const int maxm = 10000 + 10;struct Question {int a, b, c, k; } qst[maxm];int label; int A[maxn], T[maxn]; int root[maxn<<1]; int s[maxnode], lc[maxnode], rc[maxnode];#define q qst[i] #define M (L+R>>1)void build(int& x, int y, int L, int R, int v) {x = ++label;lc[x] = lc[y], rc[x] = rc[y], s[x] = s[y] + 1;if(L == R) return;if(v <= M) build(lc[x], lc[y], L, M, v);else build(rc[x], rc[y], M+1, R, v); }void modify(int& x, int L, int R, int v, int d) {if(!x) x = ++label;s[x] += d;if(L == R) return;if(v <= M) modify(lc[x], L, M, v, d);else modify(rc[x], M+1, R, v, d); }int main() {freopen("dynrank.in", "r", stdin);freopen("dynrank.out", "w", stdout);int kase;scanf("%d", &kase);while(kase--) {label = 0;int n, m, tot = 0;scanf("%d %d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%d", &A[i]);T[++tot] = A[i];}char opt[2];for(int i = 1; i <= m; i++) {scanf("%s", opt);if(opt[0] == 'Q') {q.k = 0;scanf("%d %d %d", &q.a, &q.b, &q.c);} else {q.k = 1;scanf("%d %d", &q.a, &q.b);T[++tot] = q.b;}}sort(T+1, T+tot+1);tot = unique(T+1, T+tot+1)-T-1;for(int i = 1; i <= n; i++)A[i] = lower_bound(T+1, T+tot+1, A[i])-T;// 幾個 memset 特別耗費時間, 可以巧妙地換掉 memset(root, 0, sizeof(root));memset(s, 0, sizeof(s));memset(lc, 0, sizeof(lc));memset(rc, 0, sizeof(rc));// 原始主席樹占用空間 [n+1, n+n], 記錄前綴和// 記錄增量占用空間 [1, n], 記錄某個位置的增量for(int i = 1; i <= n; i++)build(root[i + n], root[i-1 + n], 1, tot, A[i]);for(int i = 1; i <= m; i++)if(q.k == 0) {vectorq1, q2; int L = 1, R = tot, rk = q.c; // 答案區間 [L, R] if(q.a == 1) q1.push_back(root[0]); else q1.push_back(root[q.a-1 + n]); q2.push_back(root[q.b + n]); for(int x = q.a-1; x > 0; x -= (x&-x)) q1.push_back(root[x]); for(int x = q.b; x > 0; x -= (x&-x)) q2.push_back(root[x]); while(L < R) { int ls = 0; for(int x = 0; x < q1.size(); x++) ls -= s[lc[q1[x]]]; for(int x = 0; x < q2.size(); x++) ls += s[lc[q2[x]]]; if(rk <= ls) { for(int x = 0; x < q1.size(); x++) q1[x] = lc[q1[x]]; for(int x = 0; x < q2.size(); x++) q2[x] = lc[q2[x]]; R = M; } else { for(int x = 0; x < q1.size(); x++) q1[x] = rc[q1[x]]; for(int x = 0; x < q2.size(); x++) q2[x] = rc[q2[x]]; L = M + 1, rk -= ls; } } printf("%d\n", T[L]); } else { for(int x = q.a; x <= n; x += (x&-x)) modify(root[x], 1, tot, A[q.a], -1); A[q.a] = lower_bound(T+1, T+tot+1, q.b)-T; for(int x = q.a; x <= n; x += (x&-x)) modify(root[x], 1, tot, A[q.a], 1); } } return 0; }

總結

以上是生活随笔為你收集整理的COGS-257-动态排名系统-树状数组+主席树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。