给定区间求不同数的个数

                                          Different Integers

Given a sequence of integers a1, a2, ..., an and q pairs of integers (l1, r1), (l2, r2), ..., (lq, rq), find count(l1, r1), count(l2, r2), ..., count(lq, rq) where count(i, j) is the number of different integers among a1, a2, ..., ai, aj, aj + 1, ..., an.

输入描述:

The input consists of several test cases and is terminated by end-of-file.The first line of each test cases contains two integers n and q.The second line contains n integers a

1

, a

2

, ..., a

n

.

The i-th of the following q lines contains two integers l

i

and r

i

.

输出描述:

For each test case, print q integers which denote the result.

示例1

输入

复制

3 2
1 2 1
1 2
1 3
4 1
1 2 3 4
1 3

输出

复制

2
1
3

备注:

* 1 ≤ n, q ≤ 10

5

* 1 ≤ a

i

 ≤ n
* 1 ≤ l

i

, ri≤ n
* The number of test cases does not exceed 10.

把序列加长一倍,就变成了连续区间求不同数的个数。我们遍历整个序列,当有相同的数时,保留后一个数,删除前一个数,这样当遍历到第x个数的时候,可能的序列就变为了  a1 , a2 , * , *, a5, a6 ......ax;其中*代表这个数已经被删除了这样若要求区间[i,x]内不同数的个数,直接就是从i到x内不为*的数的个数,若把存在的数权值改为1,那么答案也就是sum(x)-sum(i-1),这样就可以考虑用树状数组来优化,注意这个性质求的区间其右端点必须是x。要注意遍历序列之前要先把查询离线存起来,然后对r进行升序排列,保证按顺序遍历序列的时候,查询区间右端点是依次出现的。

#include<bits/stdc++.h>
#define N 200500
using namespace std;
int last[N],team[N];
int c[N];
int Ans[N];

void updata(int x,int v)
{
    while(x<N)
    {
        c[x]+=v;
        x+=x&(-x);
    }
}

int Sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=c[x];
        x-=x&(-x);
    }
    return ans;

}

typedef struct
{
    int l,r,ans,index;

}ss;

ss qu[N];

int cmp(ss a,ss b)
{
    return a.r<b.r;
}

int main()
{
   int n,q,sum;

   while(scanf("%d %d",&n,&q)==2)
   {
       memset(last,0,sizeof(last));
       memset(c,0,sizeof(c));
       sum=0;

       for(int i=1;i<=n;i++)
       {
           scanf("%d",&team[i]);
           team[i+n]=team[i];
       }

        for(int i=1;i<=q;i++)scanf("%d %d",&qu[i].r,&qu[i].l),qu[i].index=i,qu[i].r+=n;
        sort(qu+1,qu+1+q,cmp);

      //  for(int i=1;i<=q;i++)printf("%d %d\n",qu[i].l,qu[i].r);

        int c1=1;
        for(int i=1;i<=q;i++)
        {
            for(int j=c1;j<=qu[i].r;j++)
            {
                if(last[team[j]]==0)
                {
                    updata(j,1);
                    last[team[j]]=j;

                }
                else
                {
                    updata(j,1);
                    updata(last[team[j]],-1);
                    last[team[j]]=j;

                }

            }
            c1=qu[i].r+1;

            Ans[qu[i].index]=Sum(qu[i].r)-Sum(qu[i].l-1);

        }

    for(int i=1;i<=q;i++)printf("%d\n",Ans[i]);

   }

    return 0;
}



原文地址:https://www.cnblogs.com/tian-luo/p/9338938.html

时间: 2024-10-30 06:21:52

给定区间求不同数的个数的相关文章

hdu3709(求区间内平衡数的个数)数位dp

题意:题中平衡数的定义: 以一个位置作为平衡轴,然后左右其他数字本身大小作为重量,到平衡轴的距离作为全职,实现左右平衡(即杠杆原理平衡).然后为区间[x,y]内平衡数的个数. (0 ≤ x ≤ y ≤ 1018) 解法:数位dp.如果一个数的平衡数,那么它的平衡轴位置是确定的.原来一直尝试数位dp在dfs时候列举平衡轴的位置,后来才意识到可以提前枚举平衡轴位置,然后再dfs,这样比较好写.dp[mid][pre][wei];表示对称轴是mid,计算第pre个位置以后需要力矩大小wei的数的个数.

Codeforces Round #271 (Div. 2) F.Ant colony(线段树 + 统计区间内某数的个数)

F. Ant colony Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si. In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He c

POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数

Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13771   Accepted: 5045 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries cons

SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)

DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the

lintcode - 统计比给定整数小的数的个数(两种方法)

1 class Solution { 2 public: 3 /* 4 * @param A: An integer array 5 * @param queries: The query list 6 * @return: The number of element in the array that are smaller that the given integer 7 */ 8 9 vector<int> countOfSmallerNumber(vector<int> A

SPOJ DQUERY 区间内不同数的个数 主席树

#include <iostream> #include <map> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 30010,MAXLOG = 20; struct ChairTree { int l,r; int ans; }ct[MAXN*MAXLOG]; int ctRoot[MAXN]; in

主席树的各类模板(区间第k大数【动,静】,区间不同数的个数,区间&lt;=k的个数)

取板粗 1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665 (POJ2104)http://poj.org/problem?id=2104 (POJ2761)http://poj.org/problem?id=2761 题意:求区间第K大,主席树模板题 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; t

HDU 5327 区间里由不同的数字组成的数的个数-set-(枚举)

题意:形如12345是我们要找的数,形如11是不合法的数,找出区间[a~b]里的合法数的个数,1<=a<=b<=10^5 分析:预处理,枚举从1开始到i结束的区间的合法数的个数,然后输入一个区间就输出sum[b]-sum[a-1]即可.这里借助set工具,利用它的count()函数,枚举数i,判定它是否为合法的数,方法是取它的每一位,然后在set里对这一位计数,如果 !=0,说明set里已经有相同的数字了,那么这个数就不合法,否则就插入这一位的数字. STL大法好!要善于运用 代码: #

给定你一个数n,找出在[a,b]这个区间中和n互质的数的个数。

解题思路:求[a,b]区间内与n互质的数的个数,我们可以转化为[1,b]内与n互质的数的个数减去[1,a-1]内与n互质的数的个数 而要求[1,b]内与n互质的数的个数,我们可以很自然地想到容斥原理 求解区间[a,b]中与k互质的个数 首先对k进行质数分解,然后与这个因子GCD!=1则共有n/ki个 有计算重复的部分,因此利用 容斥原理: k1+k2+k3-k1*k2-.....求出与k不互质的个数,用总的减去即可 Description 给定你一个数n,请你统计出在[a,b]这个区间中和n互质