洛谷P1972 [SDOI2009]HH的项链(离线+扫描,树状数组)

Description:

给出一个长度为n的序列,再给出m个询问[L,R]问在区间[L,R]中,有多少个不同的数。

Input:

n,m

ai

m

Li,Ri

Output:

answers

Analysis:

基于一个观察,就是,对于一个区间询问真正有意义的是最靠近区间右端点的那些数,于是考虑用离线+扫描的方式,动态维护一个树状数组

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int maxn =  500005;
const int MOD = 1e9+7;
const double eps = 1e-6;
const double pi = acos(-1);

int n,m;
int a[maxn],C[maxn<<2];

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

int Sum(int x){
    int ret=0;
    while(x>0){
        ret+=C[x];x-=lowbit(x);
    }
    return ret;
}

void Add(int x,int d){
    while(x<=n){
        C[x]+=d;x+=lowbit(x);
    }
}
struct Ask{
    int L,R,id;
    bool operator <(const Ask & rhs)const{
        return R>n){

        memset(C,0,sizeof(C));
        _rep(i,1,n) cin>>a[i];
        cin>>m;
        _rep(i,1,m){
            cin>>ask[i].L>>ask[i].R;
            ask[i].id=i;
        }

        sort(ask+1,ask+1+m);
        vector pre(1000005,0);
        int cur=1;
        for(int i=1;i<=m;++i){
            for(;cur<=ask[i].R;++cur){
                if(pre[a[cur]]){
                    Add(pre[a[cur]],-1);
                }
                Add(cur,1);
                pre[a[cur]]=cur;
            }
            int tmp=Sum(ask[i].R)-Sum(ask[i].L-1);
            ans[ask[i].id]=tmp;
        }
        _rep(i,1,m) cout<

 

你可能感兴趣的:(数据结构)