标签:rip repr mes std sum ted ios was 区间
Input
Output
Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3
Sample Output
5 6 3
Hint
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cmath> 5 #include<cstring> 6 #define N 100007 7 8 using namespace std; 9 10 struct Node 11 { 12 int l,r,rs,ls,sum; 13 }tree[N*20]; 14 int rt[N],pos,cnt; 15 int a[N],b[N]; 16 17 void build(int &node,int l,int r) 18 { 19 node=++cnt;//动态分配空间。 20 tree[node].l=l,tree[node].r=r; 21 if (l==r) return; 22 int mid=(l+r)>>1; 23 build(tree[node].ls,l,mid); 24 build(tree[node].rs,mid+1,r); 25 } 26 void insert(int pre,int &node) 27 { 28 node=++cnt; 29 tree[node].ls=tree[pre].ls,tree[node].rs=tree[pre].rs; 30 tree[node].l=tree[pre].l,tree[node].r=tree[pre].r; 31 tree[node].sum=tree[pre].sum+1; 32 if (tree[node].l==tree[node].r) return; 33 int mid=(tree[node].l+tree[node].r)>>1; 34 if (pos<=mid) insert(tree[pre].ls,tree[node].ls);//如果当前节点在左边,则只需要修改左子树就可以了。 35 else insert(tree[pre].rs,tree[node].rs);//如果当前节点在右边,则只需要修改右子树上的信息。 36 } 37 int query(int pre,int node,int k) 38 { 39 if (tree[node].ls==tree[node].rs) return b[tree[node].l];//当左儿子等于右儿子时,就可返回唯一确定的值了。 40 int cmp=tree[tree[node].ls].sum-tree[tree[pre].ls].sum;//表示左子树中有多少节点。 41 if (k<=cmp) return query(tree[pre].ls,tree[node].ls,k);//左边节点数大于k,就到左子树中找。 42 else return query(tree[pre].rs,tree[node].rs,k-cmp);//否则就在右边。 43 } 44 int main() 45 { 46 int n,q; 47 scanf("%d%d",&n,&q); 48 for (int i=1;i<=n;i++) 49 { 50 scanf("%d",&a[i]); 51 b[i]=a[i]; 52 } 53 sort(b+1,b+n+1); 54 build(rt[0],1,n); 55 for (int i=1;i<=n;i++) 56 { 57 pos=lower_bound(b+1,b+n+1,a[i])-b;//pos表示a[i]排名第几。 58 insert(rt[i-1],rt[i]);//不断加入当前节点,来更新最新的一颗子树。 59 } 60 int x,y,k; 61 for (int i=1;i<=q;i++) 62 { 63 scanf("%d%d%d",&x,&y,&k); 64 printf("%d\n",query(rt[x-1],rt[y],k));//类似前缀和这样的方式去找区间第k大的值,很神奇、 65 } 66 }
标签:rip repr mes std sum ted ios was 区间
原文地址:http://www.cnblogs.com/fengzhiyuan/p/7531338.html