SPOJ KQUERYO - K-Query Online [歸併樹/主席樹]

KQUERYO - K-Query Online
no tags
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

題意:給一個序列,q次詢問,求區間內比k大的數
題解:主席樹/歸併樹 入門題

主席樹

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=3e4+5;
int a[maxn],b[maxn];
struct node{
    int l;
    int r;
    int sum;
}nod[maxn<<5];
int root[maxn],tot;
void build(int &rt,int l,int r){
    rt=++tot;
    nod[rt].sum=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(nod[rt].l,l,mid);
    build(nod[rt].r,mid+1,r);
}
void update(int &rt,int last,int l,int r,int x){
    rt=++tot;
    nod[rt].l=nod[last].l;
    nod[rt].r=nod[last].r;
    nod[rt].sum=nod[last].sum+1;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(mid>=x)update(nod[rt].l,nod[last].l,l,mid,x);
    else update(nod[rt].r,nod[last].r,mid+1,r,x);
}
int query(int rt,int l,int r,int l0,int r0){
    if(l>=l0&&r<=r0)return nod[rt].sum;
    int mid=(l+r)>>1;
    int xx=0;
    if(mid>=l0)xx+=query(nod[rt].l,l,mid,l0,r0);
    if(mid<r0)xx+=query(nod[rt].r,mid+1,r,l0,r0);
    return xx;
}
int main ()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}
    sort(b+1,b+1+n);
    int siz=unique(b+1,b+1+n)-(b+1);
    build(root[0],1,siz);
    for(int i=1;i<=n;i++){
        int pos=lower_bound(b+1,b+1+siz,a[i])-b;
        update(root[i],root[i-1],1,siz,pos);
    }
    int q;
    scanf("%d",&q);
    int x=0;
    while(q--){
        int l,r,s;
        scanf("%d%d%d",&l,&r,&s);
        l^=x;
        r^=x;
        s^=x;
        if(l<1)l=1;
        if(r>n)r=n;
        if(l>r){
            printf("0\n");
            x=0;
            continue;
        }
        int pos=upper_bound(b+1,b+1+siz,s)-b;
        if(pos>siz){printf("0\n");x=0;}
        else{
            x=query(root[r],1,siz,pos,siz)-query(root[l-1],1,siz,pos,siz);
            printf("%d\n",x);
        }
    }
    return 0;
}

歸併樹

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=3e4+5;
int a[maxn];
vector<int>v[maxn<<2];
void merg(vector<int> &v0,vector<int> v1,vector<int> v2){
    int t1=0;
    int t2=0;
    while(t1<v1.size()&&t2<v2.size()){
        if(v1[t1]<=v2[t2]){
            v0.push_back(v1[t1]);
            t1++;
        }
        else{
            v0.push_back(v2[t2]);
            t2++;
        }
    }
    while(t1<v1.size()){
        v0.push_back(v1[t1]);
        t1++;
    }
    while(t2<v2.size()){
        v0.push_back(v2[t2]);
        t2++;
    }
}
void build(int rt,int l,int r){
    if(l==r){
        v[rt].push_back(a[l]);
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build((rt<<1)|1,mid+1,r);
    merg(v[rt],v[rt<<1],v[(rt<<1)|1]);
}
int query(int rt,int l,int r,int l0,int r0,int k){
    if(l>=l0&&r<=r0){return v[rt].size()-(upper_bound(v[rt].begin(),v[rt].end(),k)-v[rt].begin());}
    int mid=(l+r)>>1;
    int xx=0;
    if(mid>=l0)xx+=query(rt<<1,l,mid,l0,r0,k);
    if(mid<r0)xx+=query((rt<<1)|1,mid+1,r,l0,r0,k);
    return xx;
}
int main ()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){scanf("%d",&a[i]);}
    build(1,1,n);
    int q;
    scanf("%d",&q);
    int x=0;
    while(q--){
        int l,r,s;
        scanf("%d%d%d",&l,&r,&s);
        l^=x;
        r^=x;
        s^=x;
        if(l<1)l=1;
        if(r>n)r=n;
        if(l>r){
            printf("0\n");
            x=0;
            continue;
        }
        x=query(1,1,n,l,r,s);
        printf("%d\n",x);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章