标签:splay test air memset \n end sort opened number
Different Integers
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 ≤ 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; }
标签:splay test air memset \n end sort opened number
原文地址:https://www.cnblogs.com/tian-luo/p/9338938.html