CodeChef DISTNUM2 Easy Queries 节点数组线段树

Description

You are given an array A consisting of N positive integers. You have to answer Q queries on it of following type:

  • l r k : Let S denote the sorted (in increasing order) set of elements of array A with its indices between l and r. Note that set Scontains distinct elements (i.e. no duplicates).
    You need to find kth number in it. If such a number does not exist, i.e. the S has less than k elements, output -1.

All the indices in the queries are 1-based.

Input

The first line of input contains two space separated integers N and Q denoting the number of elements in A, and the number of queries, respectively.

The second line of input contains N space separated integers denoting the array A.

Each of the next Q lines contains five integers aibicidiki.
We will generate liri indices for this query as follows:

Let answer for i - 1th query equal ansi - 1.
For 0th query ans0 = 0.
Define li = (ai x max(ansi - 1, 0) + bi) mod N + 1,
ri = (ci x max(ansi-1, 0) + di) mod N + 1.
If li > ri, then swap li and ri.
	

Output

For each query, output the answer to the query in a single line. If such a number doesn‘t exist, output -1.

Constraints

  • 1 ≤ N, Q ≤ 105
  • 1 ≤ Ai ≤ 109
  • 0 ≤ aibicidi ≤ N
  • 1 ≤ li ≤ ri ≤ N
  • 1 ≤ ki ≤ N

Example

Input:
4 4
3 2 1 2
0 1 0 3 2
2 0 0 3 4
1 2 1 3 2
2 0 0 3 3

Output:
2
-1
2
3

Input:
10 10
9 10 6 3 8 4 9 6 4 10
0 2 0 9 3
1 9 1 3 3
1 8 1 0 3
1 2 1 7 2
1 6 1 2 3
1 4 1 3 1
1 6 1 6 1
1 4 1 8 1
1 9 1 3 3
1 9 1 2 1

Output:
6
9
10
4
6
3
10
4
6
4

Subtasks

  • Subtask #1 (10 points) : Q x ≤ 107
  • Subtask #2 (20 points) : ki = 1
  • Subtask #3 (30 points) : ai = 0, ci = 0
  • Subtask #4 (40 points) : Original constraints

Explanation

Example #1:

Query 1. Sorted set of elements : {1, 2}. Second number in this is 2.

Query 2. Sorted set of elements : {1, 2, 3}. Fourth number doesn‘t exist, hence answer is -1.

Query 3. Sorted set of elements : {1, 2}. Second number in this set is 2.

Query 4. Sorted set of elements : {1, 2, 3}. Third number in this set is 3.

题意:

  给定长度为N的序列A,其中每个元素都有正整数。

  你需要回答Q个询问:

    l,r,k:记s为序列 A下标在l到r之间的元素按照升序排列得到的序列(重复元素只留一个)。

    你需要求出其第k个元素的值,如果包含小于k个元素,则输出-1.

    下标从1开始编号

题解:

  线段树,每个节点保存不含重复元素的动态数组

  查询的时候二分就OK 复杂度O( q*logn*logn)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e5+10, M = 2e2+11, inf = 2e9, mod = 1e9+7;
typedef long long ll;
int n, q;
ll ar[N],num[N];
vector< ll > da[4 * N];
void merges(vector<ll> &a, vector<ll> &b, vector<ll> &c)
{
    int lenb = 0 , lenc = 0;
    while(lenb < b.size() && lenc < c.size()) {
        if(b[lenb] == c[lenc]) {
            a.push_back(b[lenb]);
            lenb++, lenc++;
        }else {
        if(b[lenb] < c[lenc]) {
            a.push_back(b[lenb++]);
        } else a.push_back(c[lenc++]);

        }
    }
    while(lenb < b.size()) {
        a.push_back(b[lenb++]);
    }
    while(lenc < c.size()) {
        a.push_back(c[lenc++]);
    }
}

void build(int k,int l,int r) {
    if(r == l) {
        da[k].push_back(ar[l]);
        return ;
    }
    build(k<<1,l,(l+r)/2);build(k<<1|1,(r+l)/2+1,r);
    merges(da[k],da[k<<1],da[k<<1|1]);
}
ll query(int i,int j,ll x,int k,int l,int r) {
    if(i==l&&j==r) return upper_bound(da[k].begin(),da[k].end(),x) - da[k].begin();
    else {
        int mid  = (l+r)>>1;
        if(j<=mid) return query(i,j,x,k<<1,l,mid);
        else if(i>mid) return query(i,j,x,k<<1|1,mid+1,r);
        else return query(i,mid,x,k<<1,l,mid)+query(mid+1,j,x,k<<1|1,mid+1,r);
    }
}

ll solve(int l,int r,int k) {
    int lb = 1, rb = n, ans = 1;
    while(lb<=rb) {
        int mid = (lb+rb)>>1;
        if(query(l,r,num[mid],1,1,n)>=k) rb = mid-1, ans = mid;
        else lb = mid + 1;
      //  cout<<1<<endl;
    }
    if(query(l,r,num[ans],1,1,n)<k) {
        return -1;
    }
    else return num[ans];
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&ar[i]), num[i] = ar[i];
    sort(num+1,num+n+1);
    build(1,1,n);
    ll pre = 0;
    for(int i=1;i<=q;i++) {
        ll a,b,c,d,k;
        scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
        int l = (a*max(pre,0ll)+b) % n + 1;
        int r = (c*max(pre,0ll)+d) % n + 1;
        printf("%d\n",pre = solve(l,r,k));
    }
}
时间: 2024-10-14 18:29:41

CodeChef DISTNUM2 Easy Queries 节点数组线段树的相关文章

SPOJ GSS5 Can you answer these queries V (线段树)

原来有一两个人说我不帅的时候,我不以为意,逗我玩而已,后来几乎所有 人都说我不帅,我才真正意识到事态的严重,这社会骗子真是越来越多了... 好吧我承认,这个笑话不好笑,其实我想说的是,做人一定要坚持自己的原则, 哪怕有一天所有人都和你背道而驰,都不要放弃自己当初的梦想,如果有一天, 我们淹没在人海之中,庸碌一生,那是因为我们不够努力,不够勇敢的去面对生活. 每天积累一点点,嗯,满足简单的快乐. ---------------------------------------------------

hdu 1166 树状数组 线段树

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 51177    Accepted Submission(s): 21427 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

hdu1394(枚举/树状数组/线段树单点更新&amp;区间求和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 或 -1, 交换两个不相邻数 a, b, 逆序数 += 两者间大于 a 的个数 - 两者间小于 a 的个数: 所以只要求出初始时的逆序对数,就可以推出其余情况时的逆序对数.对于求初始逆序对数,这里 n 只有 5e3,可以直接暴力 / 树状数组 / 线段树 / 归并排序: 代码: 1.直接暴力 1

spoj gss2 : Can you answer these queries II 离线&amp;&amp;线段树

1557. Can you answer these queries II Problem code: GSS2 Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in co

HDU 1394 Minimum Inversion Number 树状数组&amp;&amp;线段树

题目给了你一串序列,然后每次 把最后一个数提到最前面来,直到原来的第一个数到了最后一个,每次操作都会产生一个新的序列,这个序列具有一个逆序数的值,问最小的你逆序数的值为多少 逆序数么 最好想到的是树状数组,敲了一把很快,注意把握把最后一个数提上来对逆序数的影响即可, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #i

HDU 1166 敌兵布阵 (树状数组&#183;线段树)

题意  中文 动态区间和问题   只会更新点  最基础的树状数组 线段树的应用 树状数组代码 #include <bits/stdc++.h> using namespace std; const int N = 50005; int c[N], n, m; void add(int p, int x) { while(p <= n) c[p] += x, p += p & -p; } int getSum(int p) { int ret = 0; while(p > 0

SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in contests. When

Codeforces Round #225 (Div. 1) C 树状数组 || 线段树

看到这题很开心啊,有印象跟以前做过的很像,貌似最近就做过一个,以时间戳为区间来建立树状数组,然后一开始我以为题意是,给x点加val,它以下的所有节点都加-val:所以一开始就以 加 和 减 建立了两个树状数组,最后 减去就是答案,写完发现跟案例对不上啊,读了题目也没发现读错了,对于那句话 我理解错了,后来看了 这个: http://blog.csdn.net/keshuai19940722/article/details/18967661 仔细看看处理部分,我还以为分奇偶性有规律呢,后来才发现读

HDU 4417 Super Mario (树状数组/线段树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble agai