zoukankan      html  css  js  c++  java
  • 划分树模版

      1 //hdu 2665
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <cstring>
      6 
      7 using namespace std;
      8 
      9 #define ls rt<<1
     10 #define rs rt<<1|1
     11 #define lson l,m,ls
     12 #define rson m+1,r,rs
     13 
     14 #define MAXN 100010
     15 
     16 int len;
     17 int sorted[MAXN];
     18 int toLeft[20][MAXN],val[20][MAXN];
     19 
     20 void build(int d,int l,int r)
     21 {
     22     if(l==r)return;
     23     int m=(l+r)>>1;
     24     int lsame=m-l+1;//lsame表示和val_mid相等且分到左边的
     25     for(int i=l;i<=r;i++)
     26         if(val[d][i]<sorted[m])
     27             lsame--;////先假设左边的数(mid - l + 1)个都等于val_mid,然后把实际上小于val_mid的减去
     28     int lpos=l;
     29     int rpos=m+1;
     30     int same=0;
     31     for(int i=l;i<=r;i++)
     32     {
     33         if(i==l)
     34         {
     35             toLeft[d][i]=0;//toLeft[i]表示[ l , i ]区域里有多少个数分到左边
     36         }
     37         else
     38         {
     39             toLeft[d][i]=toLeft[d][i-1];
     40         }
     41         if(val[d][i]<sorted[m])
     42         {
     43             toLeft[d][i]++;
     44             val[d+1][lpos++]=val[d][i];
     45         }
     46         else if(val[d][i]>sorted[m])
     47         {
     48             val[d+1][rpos++]=val[d][i];
     49         }
     50         else
     51         {
     52             if(same<lsame)//有lsame的数是分到左边的
     53             {
     54                 same++;
     55                 toLeft[d][i]++;
     56                 val[d+1][lpos++]=val[d][i];
     57             }
     58             else
     59             {
     60                 val[d+1][rpos++]=val[d][i];
     61             }
     62         }
     63     }
     64     build(d+1,l,m);
     65     build(d+1,m+1,r);
     66 }
     67 
     68 
     69 int query(int L,int R,int k,int d,int l,int r)
     70 {
     71     if(l==r) return val[d][l];
     72     int s;//s表示[ L , R ]有多少个分到左边
     73     int ss;//ss表示 [l , L-1 ]有多少个分到左边
     74     int m=(l+r)>>1;
     75     if(L==l)
     76     {
     77         s=toLeft[d][R];
     78         ss=0;
     79     }
     80     else
     81     {
     82         s=toLeft[d][R]-toLeft[d][L-1];
     83         ss=toLeft[d][L-1];
     84     }
     85     if(s>=k)//有多于k个分到左边,显然去左儿子区间找第k个
     86         return query(l+ss,l+ss+s-1,k,d+1,l,m);
     87     else
     88         return query(m+L-l-ss+1,m-l-ss+R-s+1,k-s,d+1,m+1,r);
     89 }
     90 int main()
     91 {
     92     int n,m,t;
     93     scanf("%d",&t);
     94     while(t--)
     95     {
     96            scanf("%d%d",&n,&m);
     97            for(int i=1;i<=n;i++)
     98         {
     99             scanf("%d",&val[0][i]);
    100             sorted[i]=val[0][i];
    101            }
    102            sort(sorted+1,sorted+n+1);
    103            build(0,1,n);
    104         while(m--)
    105         {
    106              int l,r,k;
    107                scanf("%d%d%d",&l,&r,&k);
    108                 printf("%d\n",query(l,r,k,0,1,n));
    109            }
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    深入理解Java中的final关键字
    【事故处理】开车撞了人,一定要这样处理,否则后悔终生!
    spark、storm与Hadoop
    深入理解Java中的final关键字
    java并发之原子性、可见性、有序性
    java中重写equals和hashCode方法
    RESTClient插件POST方法传递参数
    Java内部类的作用
    java常用设计模式
    思辨: 讨论交流和独立思考谁更重要。
  • 原文地址:https://www.cnblogs.com/Missa/p/2701353.html
Copyright © 2011-2022 走看看