SPOJ D-query (主席树)

题目:传送门

思路:莫队板子题。。

主席树变形。以往的主席树模板题都是建立可持续化权值线段树(求区间第k大,求区间小于k的数量等),而这道题需要建立可持续化的普通线段树(维护区间而非维护值域)。

对于a[i],我们判断其之前是否出现过,如果没有,则直接在i上加个1,否则为了保证每个数字只算一次,我们在当前版本的线段树对上一次a[i]出现的位置进行-1(先开辟一条-1的链,然后在当前版本下替换的以前版本的树链,保证之前版本的线段树不受影响)。这样就能保证对于重复出现的数字,在其对应的线段树版本中,我们取最靠右的(贪心思想)。对于每一个右端点都是一个不同版本的线段树([1,x]建树)。

那么当查询 l and r 时,只需在r端点对应版本的线段树查询区间[l,r]的和即可。

#include<cctype>
#include<cstring>
#include<cstdio>
#include<functional>
#include<algorithm>
#include<cmath>
#include<queue>
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-9;
const long double pi=acos(-1.0L);
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define mem(a,b) memset(a,b,sizeof(a))
LL read()
{
    LL x=0,t=1;
    char ch;
    while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
    while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    return x*t;
}
struct node{int l,r,v;}c[N*40];
int a[N],t[N],n,m,cnt,len,root[N],last[N*10];

void update(int l,int r,int pre,int &now,int pos,int w)
{
    c[++cnt]=c[pre],c[cnt].v+=w,now=cnt;
    if(l==r) return ;
    int mid=l+r>>1;
    if(pos<=mid) update(l,mid,c[pre].l,c[now].l,pos,w);
    else update(mid+1,r,c[pre].r,c[now].r,pos,w);
}
int query(int l,int r,int ll,int rr,int y)
{
    if(ll<=l&&r<=rr) return c[y].v;
    int mid=l+r>>1,t1=0,t2=0;
    if(ll<=mid) t1=query(l,mid,ll,rr,c[y].l);
    if(rr>mid) t2=query(mid+1,r,ll,rr,c[y].r);
    return t1+t2;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        if(last[a[i]])
        {
            int tmp;
            update(1,n,root[i-1],tmp,last[a[i]],-1);
            update(1,n,tmp,root[i],i,1);
        }
        else update(1,n,root[i-1],root[i],i,1);
        last[a[i]]=i;
    }
    m=read();
    while(m--)
    {
        int x=read(),y=read();
        printf("%d\n",query(1,n,x,y,root[y]));
    }
    return 0;
}
AC代码

猜你喜欢

转载自www.cnblogs.com/DeepJay/p/12402965.html
今日推荐