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\n", ans[i]);
107     }
108     return 0;
109 }
View Code

 

posted @ 2018-10-07 10:41  Schenker  阅读(300)  评论(0编辑  收藏  举报