Live2d Test Env

SPOJ:K-Query Online(归并树)

Given a sequence of n numbers a1, a2, ..., an and a number of k-queries. A k-query is a triple (i, j, k) (1 ≤ i ≤ j ≤ n). For each k-query (i, j, k), you have to return the number of elements greater than k in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 109).
  • Line 3: q (1 ≤ q ≤ 200000), the number of k- queries.
  • In the next q lines, each line contains 3 numbers a, b, c representing a k-query. You should do the following:
    • i = a xor last_ans
    • j = b xor last_ans
    • k = c xor last_ans
    After that 1 ≤ i ≤ j ≤ n, 1 ≤ k ≤ 109 holds.
    Where last_ans = the answer to the last query (for the first query it's 0).

Output

For each k-query (i, j, k), print the number of elements greater than k in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input:
6
8 9 3 5 1 9
5
2 3 5
3 3 7
0 0 11
0 0 2
3 7 4

Output:
1
1
0
0
2

[Edited by EB]

There are invalid queries. Assume the following:

  • if i < 1: i = 1
  • if j > n: j = n
  • if i > j: ans = 0

题意:在线询问区间大于K的个数。

思路:线段树,每个节点加vector排序。

(第一次写归并树,AC on one go!

#include<bits/stdc++.h>
using namespace std;
const int maxn=1200010;
vector<int>v[maxn];
int a[maxn];
void build(int Now,int L,int R)
{
    if(L==R) { v[Now].push_back(a[L]); return ;}
    int Mid=(L+R)>>1;
    build(Now<<1,L,Mid);
    build(Now<<1|1,Mid+1,R);
    int i=0,j=0,L1=v[Now<<1].size()-1,L2=v[Now<<1|1].size()-1;
    while(i<=L1||j<=L2){
        while(i<=L1&&j<=L2){
            if(v[Now<<1][i]<=v[Now<<1|1][j]) v[Now].push_back(v[Now<<1][i++]);
            else v[Now].push_back(v[Now<<1|1][j++]);
        }
        while(j>L2&&i<=L1) v[Now].push_back(v[Now<<1][i++]);
        while(i>L1&&j<=L2) v[Now].push_back(v[Now<<1|1][j++]);
    }
}
int query(int Now,int L,int R,int l,int r,int k)
{
    if(l<=L&&r>=R) {
        int pos=lower_bound(v[Now].begin(),v[Now].end(),k)-v[Now].begin();
        return v[Now].size()-pos;
    }
    int Mid=(L+R)>>1,res=0;
    if(l<=Mid) res+=query(Now<<1,L,Mid,l,r,k);
    if(r>Mid) res+=query(Now<<1|1,Mid+1,R,l,r,k);
    return res;
}
int main()
{
    int N,Q,ans=0,i,j,k;
    scanf("%d",&N);
    for(i=1;i<=N;i++) scanf("%d",&a[i]);
    build(1,1,N);
    scanf("%d",&Q);
    while(Q--){
        scanf("%d%d%d",&i,&j,&k);
        i=i^ans; j=j^ans; k=k^ans;
        if(i<1) i=1; if(j>N) j=N;
        if(i>j) ans=0;
        else ans=query(1,1,N,i,j,k+1);
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2018-05-17 22:55  nimphy  阅读(371)  评论(2编辑  收藏  举报