P1972 [SDOI2009]HH的项链
P1972 [SDOI2009]HH的项链
这题看起来可以用莫队做,本来想水一下的,然而我逛了一圈题解发现数据被加强了。
我稍微想了一下主席树,感觉好像维护起来没什么用,可能是我太菜了。
Std:
个人的理解
其实这种想法就是在进行一种去重(消去重复的影响),让统计变成最简单的区间求和
既然我们区间颜色重叠会影响统计,那么我们只要记录当前最有效的颜色即可,区间右端点的排序保证了这种有效性。
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1000305
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
inline int read()
{
int ans=0;
char last=' ',ch=getchar();
while(ch<'0'|ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
struct Query
{
int l,r,id;
bool operator<(const Query& sec)const
{
return r<sec.r;
}
}q[maxn];
int tree[maxn];
int a[maxn],ans[maxn],pos[maxn];
int n,m;
void renew(int x,int k)
{
for(;x<=n;x+=(x&-x))tree[x]+=k;
}
int cal(int x)
{
int t=0;
for(;x;x-=(x&-x))t+=tree[x];
return t;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
}
m=read();
for(int i=0;i<m;i++)
{
q[i].l=read(),q[i].r=read();q[i].id=i;
}
sort(q,q+m);
int cur=0;
for(int i=0;i<m;i++)
{
while(cur<q[i].r)
{
cur++;
if(pos[a[cur]]!=0)renew(pos[a[cur]],-1);
renew(cur,1);
pos[a[cur]]=cur;
}
ans[q[i].id]=cal(q[i].r)-cal(q[i].l-1);
}
for(int i=0;i<m;i++)
{
cout<<ans[i]<<"\n";
}
return 0;
}