[SDOI2009]HH的项链 [树状数组]

1972 [SDOI2009]HH的项链 

一段区间包含了多少种不同的数字

emmmm有很多种做法 莫队 主席树 线段树....我觉得这题还挺好的

我比较弱就用的树状数组 得离线

关键点是要将右端点r作为关键字 若前面出现过 就将其消掉 转移到当前

for(int i=1;i<=m;++i){
    for(int j=nxt;j<=ask[i].r;++j){
        if(in[a[j]]) update(in[a[j]],-1);
        update(j,1),in[a[j]]=j;
     }

这一坨把它比比划划就能明白了 尽量将其往后挪 因为是离线(语无伦次)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)>(y)?(y):(x)
#define ll long long
#define rg register
const int N=500000+5,M=200000+5,inf=0x3f3f3f3f,P=99999997;
int n,m,tree[N<<2],a[N<<1],in[N<<1],ans[N<<1];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

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

void update(int pos,int ad){
    while(pos<=n) tree[pos]+=ad,pos+=lowbit(pos);
}

int query(int pos){
    int ans=0;
    while(pos>0) ans+=tree[pos],pos-=lowbit(pos);
    return ans;
}

struct node{int l,r,pos;}ask[N];
bool cmp(node a,node b){return a.r<b.r;}

int main(){
//    freopen("in.txt","r",stdin);
    rd(n); 
    for(int i=1;i<=n;++i) rd(a[i]);
    rd(m);
    for(int i=1;i<=m;++i) rd(ask[i].l),rd(ask[i].r),ask[i].pos=i;
    sort(ask+1,ask+1+m,cmp);
    int nxt=1;
    for(int i=1;i<=m;++i){
        for(int j=nxt;j<=ask[i].r;++j){
            if(in[a[j]]) update(in[a[j]],-1);
            update(j,1),in[a[j]]=j;
        }
        ans[ask[i].pos]=query(ask[i].r)-query(ask[i].l-1);
        nxt=ask[i].r+1;
    }
    for(int i=1;i<=m;++i) printf("%d
",ans[i]);
    return 0;
}
 
原文地址:https://www.cnblogs.com/lxyyyy/p/11179777.html