Sequence II——区间第k+区间不同元素数量

Description

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

In the i-th query, you are given two integers and . Consider the subsequence .

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

Note that is the number of different integers in this subsequence. You should output for the i-th query.
Input

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

Each test case starts with two integers n () and m (). There are n integers in the next line, which indicate the integers in the sequence(i.e., ).

There are two integers and 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 . As a result, the problem became more exciting.

We can denote the answers as . Note that for each test case .

You can get the correct input from what you read (we denote them as )by the following formula:

扫描二维码关注公众号,回复: 2714270 查看本文章

Output

You should output one single line for each test case.

For each test case, output one line “Case #x: ”, where x is the case number (starting from 1) and 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

原文链接http://acm.hdu.edu.cn/showproblem.php?pid=5919

他的意思就是给你一串数字,再给m个询问,因为要求在线处理所以需要加上上一次求出来的答案再算出最终区间不同数字的个数k,输出第(k+1)/2个数,这里需要从后往前建树,这样在查询的时候l前面的数就不会加进来,比较方便。
注意!!!这里的数组是要开到40倍左右的,30都过不了,一直T

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
int sum[maxn*40],ls[maxn*40],rs[maxn*40],rt[maxn],pre[maxn],a[maxn];
int n,m,tot;
void build(int l,int r,int &root)
{
    root=++tot;
    sum[root]=0;
    if(l==r)
        return ;
    int mid=l+r>>1;
    build(l,mid,ls[root]);
    build(mid+1,r,rs[root]);
}
void update(int l,int r,int root,int last,int pos,int val)
{
    ls[root]=ls[last];
    rs[root]=rs[last];
    sum[root]=sum[last]+val;
    if(l==r)
        return ;
    int mid=l+r>>1;
    if(mid>=pos)
        update(l,mid,ls[root]=++tot,ls[last],pos,val);
    else
        update(mid+1,r,rs[root]=++tot,rs[last],pos,val);
}
int query1(int l,int r,int root,int ql,int qr)
{
    if(l>=ql&&r<=qr)
        return sum[root];
    int mid=l+r>>1;
    int ans=0;
    if(mid>=ql)
        ans+=query1(l,mid,ls[root],ql,qr);
    if(mid<qr)
        ans+=query1(mid+1,r,rs[root],ql,qr);
    return ans;
}
int query2(int l,int r,int q,int k)
{
    if(l==r)
        return l;
    int mid=l+r>>1;
    if(sum[ls[q]]>=k)
        return query2(l,mid,ls[q],k);
    else
        return query2(mid+1,r,rs[q],k-sum[ls[q]]);
}
int main()
{
    int t;
    scanf("%d",&t);
    int cas=0;
    while(t--)
    {
        memset(pre,0,sizeof(pre));
        tot=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        build(1,n,rt[n+1]);
        for(int i=n;i>=1;i--)
        {
            if(pre[a[i]])
            {
                update(1,n,rt[i]=++tot,rt[i+1],pre[a[i]],-1);
                int now=++tot;
                update(1,n,now,rt[i],i,1);
                rt[i]=now;
            }
            else
                update(1,n,rt[i]=++tot,rt[i+1],i,1);
            pre[a[i]]=i;
        }
        int ans=0,l,r;
        printf("Case #%d: ",++cas);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            l=(l+ans)%n+1;
            r=(r+ans)%n+1;
            if(l>r)
                swap(l,r);
            int k=query1(1,n,rt[l],l,r);
            ans=query2(1,n,rt[l],(k+1)/2);
            printf("%d%c",ans,i==m?'\n':' ');
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/81586714
今日推荐