C52 可持久化线段树 P1972 [SDOI2009] HH的项链

视频链接:C52 可持久化线段树 P1972 [SDOI2009] HH的项链_哔哩哔哩_bilibili

 

 

 

Luogu P1972 [SDOI2009] HH的项链

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=1000005;
#define mid ((l+r)>>1)
int n,m,a[N],last[N]; //ai上次出现的位置
int root[N],tot;      //根节点,节点个数
int ls[N*40],rs[N*40],sum[N*40];
//sum:区间数的出现次数之和

void change(int &u,int v,int l,int r,int p,int k){ //点修
  u=++tot; //动态开点
  ls[u]=ls[v];rs[u]=rs[v];sum[u]=sum[v]+k;
  if(l==r) return;  //双指针同步搜索
  if(p<=mid) change(ls[u],ls[v],l,mid,p,k);
  else change(rs[u],rs[v],mid+1,r,p,k);
}
int query(int u,int l,int r,int p){ //点查
  if(l==r) return sum[u];
  if(p<=mid) return query(ls[u],l,mid,p)+sum[rs[u]];
  else return query(rs[u],mid+1,r,p);
}
int main(void){
  scanf("%d",&n);
  for(int i=1; i<=n; ++i) scanf("%d",a+i);
  for(int i=1,rt; i<=n; ++i){
    if(!last[a[i]])change(root[i],root[i-1],1,n,i,1);
    else{
      change(rt,root[i-1],1,n,last[a[i]],-1);
      change(root[i],rt,1,n,i,1);
    }
    last[a[i]]=i; //记录ai的出现位置
  }
  scanf("%d",&m); int l,r;
  while(m--){
    scanf("%d%d",&l,&r);
    printf("%d\n",query(root[r],1,n,l));
  }
  return 0;
}

 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

int read(){
  int s=0; char c=getchar();
  while(c<'0'||c>'9') c=getchar();
  while(c>='0'&&c<='9') s=s*10+c-'0',c=getchar();
  return s;
}
const int N=1000005;
#define mid ((l+r)>>1)
int n,m,a[N],last[N]; //ai上次出现的位置
int root[N],tot;      //根节点,节点个数
int ls[N*40],rs[N*40],sum[N*40];
//sum:区间数的出现次数之和

void change(int &u,int v,int l,int r,int p,int k){ //点修
  u=++tot; //动态开点
  ls[u]=ls[v];rs[u]=rs[v];sum[u]=sum[v]+k;
  if(l==r) return;  //双指针同步搜索
  if(p<=mid) change(ls[u],ls[v],l,mid,p,k);
  else change(rs[u],rs[v],mid+1,r,p,k);
}
int query(int u,int l,int r,int p){ //点查
  if(l==r) return sum[u];
  if(p<=mid) return query(ls[u],l,mid,p)+sum[rs[u]];
  else return query(rs[u],mid+1,r,p);
}
int main(){
  n=read();
  for(int i=1; i<=n; ++i) a[i]=read();
  for(int i=1,rt; i<=n; ++i){
    if(!last[a[i]])change(root[i],root[i-1],1,n,i,1);
    else{
      change(rt,root[i-1],1,n,last[a[i]],-1);
      change(root[i],rt,1,n,i,1);
    }
    last[a[i]]=i; //记录ai的出现位置
  }
  m=read(); int l,r;
  while(m--){
    l=read(); r=read();
    printf("%d\n",query(root[r],1,n,l));
  }
  return 0;
}

 

posted @ 2023-10-26 13:59  董晓  阅读(220)  评论(0编辑  收藏  举报