牛客网多校赛第一场 J Different Integers

今天早上6点多醒过来自学树状数组,然后弄懂了这道题

树状数组   这个博客不错,讲的通俗易懂

思路:本来是一个数组从中间截断,很难想,但是换一种思路,将前面一段数组拼到后面,就成了在一段区间一段连续的数组求有多少个不同个数,之后就可以用树状数组求啦。

#include<bits/stdc++.h>
using namespace std;  
typedef long long ll;  
#define  Max  int(2e5+10)
int n,p,a[Max],c[Max],resu[Max],vis[Max];

struct query
{
  int l,r,pos;	
}q[Max];

bool operator <(query x,query y)
{ 
   return x.r<y.r;	
}

int lowbit(int x)
{
	return x&(-x);
}

void add(int x,int d)
{
	while(x<Max)
	{
		c[x]+=d;
		x+=lowbit(x);
	}
}

int sum(int x)
{
	int su=0;
	while(x>0)
	{
		su+=c[x];
		x-=lowbit(x);
	}
	return su;
}

int main()
{
	while(~scanf("%d%d",&n,&p))
    {
		memset(c,0,sizeof c);
		for(int i=1;i<=n;i++)
		   {
		   	scanf("%d",&a[i]);
		   	a[n+i]=a[i];
		   }
	    int l,r;
	    for(int i=1;i<=p;i++)
	       {
	       	scanf("%d%d",&l,&r);
	       	q[i].l=r;
	       	q[i].r=l+n;
	       	q[i].pos=i;
		   }
		   sort(q+1,q+1+p);
		   n*=2;
		   memset(vis,0,sizeof vis);
		   for(int i=1,j=1;i<=n&&j<=p;i++)
		   {
		   	 if(vis[a[i]]) 
	        	add(vis[a[i]],-1);
			  add(i,1);
			  vis[a[i]]=i;
			  while(j<=p&&q[j].r<=i)
			  {
			     resu[q[j].pos]=sum(q[j].r)-sum(q[j].l-1);
				 j++;	
			  }		   	    	
		   }
		   
		   for(int i=1;i<=p;i++)
		      printf("%d\n",resu[i]);
    }
} 

猜你喜欢

转载自blog.csdn.net/pinkair/article/details/81139877