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
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; }
It is your time to fight!