Luogu P1972 [SDOI2009] HH's Necklace Problem Solution

It can be found that this topic is very difficult to do online (maybe there are some gods who can do it...), so (this konjac) can only use the offline method. The specific method is as follows: first, put all the The queries are sorted according to the right endpoint, regardless of the left endpoint, and then each query is done in order. How to do it, see below:

For example, we are currently doing a query, its left endpoint is l, and its right endpoint is r, then we need to process the first r shells in the necklace, because r is in ascending order, so this processing actually only takes linear time, So currently we should deal with shells in the 1~r range, first define an s[i], the usage will be mentioned later, so how to deal with it? For each type of shell, we make the s value of the latest of all such shells—that is, the rightmost one—to be 1, and the others to be 0. After processing, we can directly count l The sum of the s values ​​in ~r is enough, which ensures that each type of shell will only be counted one, then the interval and this thing can be maintained by a tree array , so that the time complexity will be very good, and In fact, the s array does not need to appear. So next... on the code!

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n,m,a[500010],last[1000010];//last records the last position of each color
struct node{int x,y,z;};
node b [200010];
int tree[500010];//Tree array
int lowbit(int x){return ((-x)&x);}
bool cmp(node ​​x,node y){return xy<yy;}//The right endpoint is the key
void change(int x,int y)//modify
{
	if(x==0)return;
	for(int i=x;i<=n;i+=lowbit(i))
	tree[i]+=y;
}
int sum(int x)//Query
{
	int p=0;
	for(int i=x;i>=1;i-=lowbit(i))
	p+=tree[i];
	return p;
}
int years[200010];

intmain()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	memset(last,0,sizeof(last));
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	scanf("%d %d",&b[i].x,&b[i].y),b[i].z=i;//b[i].z is used to record the query number for easy output
	sort(b+1,b+m+1,cmp);//sort
	int j=0;//Record which shell was processed
	memset(tree,0,sizeof(tree));//
	for(int i=1;i<=m;i++)
	{
		while(j<b[i].y)//
		{
			j++;
			change(last[a[j]],-1);//Remove the previous mark
			last[a[j]]=j;//Record
			change(j,1);//Remark
		}
		ans[b[i].z]=sum(b[i].y)-sum(b[i].x-1);//Statistical interval sum and record
	}
	for(int i=1;i<=m;i++)
	printf("%d\n",ans[i]);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324952282&siteId=291194637