HDU 5919 Sequence II 主席树

Posted Meek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5919 Sequence II 主席树相关的知识,希望对你有一定的参考价值。

Sequence II




Problem Description
 
Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?,an There are m queries.

In the i-th query, you are given two integers li and ri. Consider the subsequence ali,ali+1,ali+2,?,ari.

We can denote the positions(the positions according to the original sequence) where an integer appears first in this subsequence as p(i)1,p(i)2,?,p(i)ki (in ascending order, i.e.,p(i)1<p(i)2<?<p(i)ki).

Note that ki is the number of different integers in this subsequence. You should output p(i)ki2for the i-th query.
 

 

Input
 
In the first line of input, there is an integer T (T2) denoting the number of test cases.

Each test case starts with two integers n (n2×105) and m (m2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,?,an,0ai2×105).

There are two integers li and ri in the following m lines.

However, Mr. Frog thought that this problem was too young too simple so he became angry. He modified each query to li,ri(1lin,1rin). As a result, the problem became more exciting.

We can denote the answers as ans1,ans2,?,ansm. Note that for each test case ans0=0.

You can get the correct input li,ri from what you read (we denote them as li,ri)by the following formula:
li=min{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}

ri=max{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}
 

 

Output
 
You should output one single line for each test case.

For each test case, output one line “Case #x: p1,p2,?,pm”, where x is the case number (starting from 1) and p1,p2,?,pm is the answer.
 

 

Sample Input
 
2 5 2 3 3 1 5 4 2 2 4 4 5 2 2 5 2 1 2 2 3 2 4
 

 

Sample Output
 
Case #1: 3 3 Case #2: 3 1
Hint
技术分享
 

 

题意:
  给定一个序列nn,有mm次查询,每次查询一个区间[l,r][l,r],求区间中每一种数在区间中第一次出现的位置的中位数,强制在线。
题解:
  强制在线
  利用主席树求区间不同数的个数
  这里有个技巧
  倒着插入主席树
  在寻找位置的中位数上就可以一个log解决了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10, M = 1e6, mod = 1e9+7, inf = 2e9;

int T,n,q,a[N],l[N*36],r[N*36],v[N*36],sz,root[N],ans[N],last[N];

void update(int x, int &y, int ll, int rr, int k,int c) {
     y = ++sz;
     v[y] = v[x] + c;
     r[y] = r[x];
     l[y] = l[x];
     if(ll == rr) return ;
     int mid = (ll+rr)>>1;
     if(k <= mid) update(l[x], l[y], ll, mid, k,c);
     else update(r[x], r[y], mid + 1, rr, k,c);
}
int query(int x,int ll,int rr,int s,int t) {
    if (s <= ll && rr <= t) return v[x];
    int mid = ll + rr >> 1, res = 0;
    if (s <= mid) res += query(l[x], ll, mid, s, t);
    if (t > mid) res += query(r[x], mid + 1, rr, s, t);
    return res;
}

int finds(int x,int ll,int rr,int k) {
        if(ll == rr) return ll;
        int mid = ll + rr >> 1;
        if(v[l[x]] >= k) return finds(l[x],ll,mid,k);
        else return finds(r[x],mid+1,rr,k-v[l[x]]);
}

int main() {
        int cas = 0;
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d",&n,&q);
            sz = 0;
            memset(last,0,sizeof(last));
            memset(v,0,sizeof(v));
            memset(l,0,sizeof(l));
            memset(r,0,sizeof(r));
            ans[0] = 0;
            root[n+1] = 0;
            for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);
            for(int i = n; i >= 1; --i) {
                int x = root[i] = 0;
                update(root[i+1],x,1,n,i,1);
                if(last[a[i]]) {
                    update(x,root[i],1,n,last[a[i]],-1);
                } else root[i] = x;
                last[a[i]] = i;
            }
            int L,R;
            for(int i = 1; i <= q; ++i) {
                scanf("%d%d",&L,&R);
                L = ((L + ans[i-1])%n) + 1;
                R = ((R + ans[i-1])%n) + 1;
                if(L > R) swap(L,R);
                int sum = query(root[L],1,n,L,R)  + 1 >> 1;
                ans[i] = finds(root[L],1,n,sum);
            }
            printf("Case #%d: ",++cas);
            for(int i = 1; i < q; ++i)  printf("%d ",ans[i]);
            cout<<ans[q]<<endl;
        }
        return 0;
}

 

以上是关于HDU 5919 Sequence II 主席树的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5919 Sequence II(主席树+逆序思想)

HDU 5919 -- Sequence II (主席树)

HDU 5919 Sequence II ( 主席树 )

HDU 5919 Sequence II

HDU 5919 Sequence II(主席树)题解

hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)