POJ-2104 K-th Number CDQ分治
Posted mingsd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ-2104 K-th Number CDQ分治相关的知识,希望对你有一定的参考价值。
题意:给你一个序列,长度为n,m次询问,询问一段区间的第k大。
题解:CDQ分治,对整个值域进行分治。每次取一个mid, 计算出整个区间内mid <= 的数目,如果 num >= k, 那么就可以第k大的数一定落在[ l, mid]之间, 否者就会落在 [mid+1, r]之间, 然后我们继续递归二分下去,直到 l == r 那么就找到第k大了。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<queue> 5 #include<iostream> 6 #include<cstring> 7 using namespace std; 8 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 9 #define LL long long 10 #define ULL unsigned LL 11 #define fi first 12 #define se second 13 #define pb push_back 14 #define lson l,m,rt<<1 15 #define rson m+1,r,rt<<1|1 16 #define lch(x) tr[x].son[0] 17 #define rch(x) tr[x].son[1] 18 #define max3(a,b,c) max(a,max(b,c)) 19 #define min3(a,b,c) min(a,min(b,c)) 20 typedef pair<int,int> pll; 21 const int inf = 0x3f3f3f3f; 22 const LL INF = 0x3f3f3f3f3f3f3f3f; 23 const LL mod = (int)1e9+7; 24 const int N = 2e5 + 100; 25 int n; 26 struct Node{ 27 int op; 28 int L, R; 29 int x, id; 30 }A[N], lf[N], ri[N]; 31 int tot = 0; 32 void NowNode(int op, int L, int R, int x, int id){ 33 ++tot; 34 A[tot].op = op; A[tot].L = L; A[tot].R = R; 35 A[tot].x = x; A[tot].id = id; 36 } 37 int ans[N]; 38 int tree[N]; 39 int Mn = inf, Mx = 0; 40 void Add(int x, int v){ 41 for(int i = x; i <= n; i += i & (-i)){ 42 tree[i] += v; 43 } 44 } 45 int Query(int x){ 46 int ret = 0; 47 for(int i = x; i; i -= i&(-i)){ 48 ret += tree[i]; 49 } 50 return ret; 51 } 52 void cdq(int Lval, int Rval, int st, int ed){ 53 if(Lval > Rval || st > ed) return ; 54 if(Lval == Rval){ 55 for(int i = st; i <= ed; i++) 56 if(A[i].op == 1) ans[A[i].id] = Lval; 57 return ; 58 } 59 int mid = Lval + Rval >> 1; 60 61 int lsz = 0, rsz = 0; 62 for(int i = st; i <= ed; i++){ 63 int op = A[i].op, x = A[i].x, L = A[i].L, R = A[i].R, id = A[i].id; 64 if(op == 0){ 65 if(x <= mid){ 66 Add(A[i].id, 1); 67 lf[++lsz] = A[i]; 68 } 69 else ri[++rsz] = A[i]; 70 } 71 else if(A[i].op == 1){ 72 int num = Query(R) - Query(L-1); 73 if(num >= x) lf[++lsz] = A[i]; 74 else { 75 A[i].x -= num; 76 ri[++rsz] = A[i]; 77 } 78 } 79 } 80 for(int i = 1; i <= lsz; i++) { 81 82 if(lf[i].op == 0) { 83 Add(lf[i].id, -1); 84 } 85 A[st + i - 1] = lf[i]; 86 } 87 for(int i = 1; i <= rsz; i++) A[st + lsz + i - 1] = ri[i]; 88 cdq(Lval, mid, st, st+lsz-1); 89 cdq(mid+1, Rval, st+lsz, ed); 90 } 91 int main(){ 92 int m, val, l, r; 93 scanf("%d%d", &n, &m); 94 for(int i = 1; i <= n; i++){ 95 scanf("%d", &val); 96 NowNode(0,0,0,val,i); 97 Mn = min(Mn, val); 98 Mx = max(Mx, val); 99 } 100 for(int i = 1; i <= m; i++){ 101 scanf("%d%d%d", &l, &r, &val); 102 NowNode(1,l,r,val,i); 103 } 104 cdq(Mn,Mx,1,n+m); 105 for(int i = 1; i <= m; i++){ 106 printf("%d ", ans[i]); 107 } 108 return 0; 109 }
以上是关于POJ-2104 K-th Number CDQ分治的主要内容,如果未能解决你的问题,请参考以下文章