题意:
给定一段区间,以及多次查询其中某段区间内的种类数。
三种做法:
离线+树状数组:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
const int maxm=2222222;
int tree[maxn];
int inline lowbit(int x) {
return x&(-x);
}
void add(int x,int val) {
for(int i=x;i<maxn;i+=lowbit(i)) {
tree[i]+=val;
}
}
int query(int x) {
int sum=0;
for(int i=x;i;i-=lowbit(i))
{
sum+=tree[i];
}
return sum;
}
int num[maxn];
void inline read(int & ret) {
char c;
ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') {
ret=ret*10+c-'0';c=getchar();
}
}
struct Node{
int l,r,index;
bool operator < (const Node & t) const {
return r<t.r;
}
}nodes[maxm];
int last[maxn];
int ans[maxm];
set<pair<int,int> > st;
inline void init() {
memset(tree,0,sizeof(tree));
memset(last,-1,sizeof(last));
st.clear();
}
int main()
{
#ifdef LOCAL_DEBUG
// freopen("test.txt","r",stdin);
#endif
int n,m;
while(~scanf("%d",&n)) {
map<int,int> mp;
init();
for(int i=1;i<=n;i++) {
read(num[i]);
// cout<<num[i]<<endl;
}
read(m);
int tmpl,tmpr;
for(int i=1;i<=m;i++) {
read(nodes[i].l);
read(nodes[i].r);
nodes[i].index=i;
}
sort(nodes+1,nodes+1+m);
int index=1;
for(int i=1;index<=m&&i<=n;i++) {
if(last[num[i]]!=-1) add(last[num[i]],-1);
add(i,1);
// for(int i=1;i<=n;i++) {
// cout<<tree[i]<<' ';
// }
// cout<<endl;
last[num[i]]=i;
while(nodes[index].r<=i&&index<=m) {
// cout<<"index:"<<index<<endl;
ans[nodes[index].index]=query(nodes[index].r)-query(nodes[index].l-1);
index++;
}
}
for(int i=1;i<=m;i++) {
printf("%d\n",ans[i]);
}
}
}
主席树在线:
#include<bits/stdc++.h>
using namespace std;
const int maxn=33333,maxs=2e6;
int n,q,num[maxn],last[maxs],cnt;
int rt[maxn];
struct Node
{
int L,R,l,r,s;
} nodes[maxn*30];
inline int red()
{
int tot=0,f=1;
char ch=getchar();
while (ch<'0'||'9'<ch)
{
if (ch=='-')
f=-f;
ch=getchar();
}
while ('0'<=ch&&ch<='9')
tot=tot*10+ch-48,ch=getchar();
return tot;
}
void update(int L,int R,int &now,int last,int pos,int val) {
now=++cnt;
nodes[now]=nodes[last];
nodes[now].s+=val;
if(L==R) return ;
int mid=(L+R)>>1;
if(mid>=pos) update(L,mid,nodes[now].l,nodes[last].l,pos,val);
else update(mid+1,R,nodes[now].r,nodes[last].r,pos,val);
}
int query(int L,int R,int l,int root) {
// cout<<"L="<<L<<" R="<<R<<endl;
if(L>=l) return nodes[root].s;
int mid=(L+R)>>1;
if(mid>=l) return nodes[nodes[root].r].s+query(L,mid,l,nodes[root].l);
else return query(mid+1,R,l,nodes[root].r);
}
void init() {
memset(nodes,0,sizeof(nodes));
cnt=0;
rt[0]=nodes[0].l=nodes[0].r=nodes[0].s=0;
memset(last,0,sizeof(last));
}
int main() {
//{
//#ifdef LOCAL_DEBUG
// freopen("test.txt","r",stdin);
//#endif
while(~scanf("%d",&n)) {
init();
int tmp;
for (int i=1; i<=n; i++)
{
num[i]=red();
// cout<<"num[i]="<<num[i]<<endl;
if(last[num[i]]) {
update(1,n,tmp,rt[i-1],last[num[i]],-1);
update(1,n,rt[i],tmp,i,1);
}
else update(1,n,rt[i],rt[i-1],i,1);
last[num[i]]=i;
// cout<<"tree "<<i<<endl;
// print(rt[i]);
}
q=red();
while (q--)
{
int l=red(),r=red();
// cout<<l<<' '<<r<<endl;
printf("%d\n",query(1,n,l,rt[r]));
}
}
}