主席树板子 p2104

 1 #include
 2 #include
 3 #include
 4 using namespace std;
 5 const int maxn=1e5+10;
 6 int n,m,cnt,root[maxn];
 7 int b[maxn],a[maxn];
 8 struct node{int l,r,sum;}T[maxn*40];
 9 void update(int l,int r,int &x,int y,int pos)
10 {
11     //这里&的这种用法我不太清楚,大概就是能值传会root[];
12     //这里T[++cnt]的值先从root[y](也就是上一颗树)传过来,然后再
13     //多拉出几个节点,去连接与之前的树相关的节点(同样是传值这一步操作)
14     T[++cnt]=T[y],T[cnt].sum++,x=cnt;
15     if(l==r) return;
16     int mid=(l+r)/2;
17     if(mid>=pos) update(l,mid,T[x].l,T[y].l,pos);
18     else update(mid+1,r,T[x].r,T[y].r,pos);
19 }
20 int query(int l,int r,int x,int y,int pos)
21 {
22     if(l==r) return l;
23     int mid=l+r>>1;
24     //这里如果sum>=pos,证明第pos大的值就在左边了,所以只需要枚举左边;
25     //否则枚举右边;
26     int sum=T[T[y].l].sum-T[T[x].l].sum;
27     if(sum>=pos) return query(l,mid,T[x].l,T[y].l,pos);
28     //右边的操作与左边大致相同,但是需要pos-sum,把前面的数去掉,
29     //因为右数是从1重新开始计数的。
30     else return query(mid+1,r,T[x].r,T[y].r,pos-sum);
31 }
32 int main()
33 {
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
36     sort(b+1,b+1+n);
37     //离散化,为什么要离散化呢。因为主席树需要开的内存很大,
38     //离散化能降低内存;
39     int t=unique(b+1,b+1+n)-b-1;
40     for(int i=1;i<=n;i++){
41         //取出离散化后的值;
42         int tmp=lower_bound(b+1,b+1+t,a[i])-b;
43         update(1,n,root[i],root[i-1],tmp);
44     }
45     for(int i=1;i<=m;i++){
46         int x,y,k;
47         scanf("%d%d%d",&x,&y,&k);
48         //求出query后,再放进b数组,还原为之前的值。
49         printf("%d\n",b[query(1,n,root[x-1],root[y],k)]);
50     }
51     return 0;
52 }

 

你可能感兴趣的:(主席树板子 p2104)