[SP3267]DQUERY - D-query 主席树

[SP3267]

  • 就是区间内本质不同数的计数的在线做法
  • 每个颜色x记录一个last[x]表示改颜色上一次出现的位置,每次把last[x]的位置-1,x现在的位置+1,保证本质不同的数贡献为1
  • 每次修改两条链,需要建一个辅助根节点
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
using namespace std;
const int inf=1e6+10;
int lc[inf<<2],rc[inf<<2],sum[inf<<2],root[inf],last[inf],SUM,tot,l,r,x,n,m;
inline int read(){
    int num=0;char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
    return num;
}
inline ll print(ll x){if(x>9)print(x/10);putchar(x%10+'0');}
void update(int &o,int last,int L,int R,int pos,int val){
    o=++tot; int M=L+R>>1;
    sum[o]=sum[last]+val,lc[o]=lc[last],rc[o]=rc[last];
    
    if(L==R)return;
    if(pos<=M)update(lc[o],lc[last],L,M,pos,val);
    else update(rc[o],rc[last],M+1,R,pos,val);
}
void query(int o,int L,int R,int ql,int qr){
    int M=L+R>>1;
    if(ql<=L&&R<=qr){
        SUM+=sum[o];
        return;
    }
    if(ql<=M)query(lc[o],L,M,ql,qr);
    if(M<qr)query(rc[o],M+1,R,ql,qr);
}
int main()
{
    n=read();
    rep(i,1,n){
        x=read();
        if(last[x]==0){
            update(root[i],root[i-1],1,inf,i,1);
        }else{
            int t;
            update(t,root[i-1],1,inf,last[x],-1);
            update(root[i],t,1,inf,i,1);
        }last[x]=i;
    }
    m=read();
    while(m--){
        l=read(),r=read();
        SUM=0;
        if(l>1)query(root[r],1,inf,1,l-1);
        print(sum[root[r]]-SUM);
        puts("");
    }return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值