C52 可持久化线段树 P1972 [SDOI2009] HH的项链
视频链接:C52 可持久化线段树 P1972 [SDOI2009] HH的项链_哔哩哔哩_bilibili
#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; }