區間查不重複元素的個數
阿新 • • 發佈:2021-08-12
某位大佬用線段樹做的 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=3e5+7; inline int read(){ int sum=0,f=1;char c=getchar(); while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){sum=sum*10+c-'0';c=getchar();}return sum*f; } int n,m,s[2*N],lt[N]; int minx[N],maxn[N]; struct Tree{ int l,r; int sum; Tree(){sum=0;} }t[7*N]; inline void build(int p,int l,int r){ t[p].l=l,t[p].r=r; if(l==r) return; int mid=(l+r)>>1; build(p*2,l,mid); build(p*2+1,mid+1,r); } inline int q_sum(int p,intql,int qr){ int l=t[p].l,r=t[p].r; if(l==r) return t[p].sum; if(ql<=l&&qr>=r) return t[p].sum; int mid=(l+r)>>1; if(ql<=mid&&qr>mid) return q_sum(p*2,ql,mid)+q_sum(p*2+1,mid+1,qr); if(qr<=mid) return q_sum(p*2,ql,qr); if(ql>mid) return q_sum(p*2+1,ql,qr); return 0; } inline void revise(int p,int x,int w){//將x位改為w int l=t[p].l,r=t[p].r; if(l==r){ t[p].sum=w; return; } int mid=(l+r)>>1; if(l<=x&&x<=mid) revise(p*2,x,w); else revise(p*2+1,x,w); t[p].sum=t[p*2].sum+t[p*2+1].sum; } int main(){ n=read(),m=read(); build(1,1,n+m); for(int i=n;i>=1;i--){ s[n-i+1]=i,lt[i]=n-i+1; revise(1,n-i+1,1); minx[i]=i; } for(int i=n+1;i<=n+m;i++){ s[i]=read(); minx[s[i]]=1; maxn[s[i]]=max(maxn[s[i]],q_sum(1,lt[s[i]],i)); revise(1,lt[s[i]],0); revise(1,i,1); lt[s[i]]=i; } for(int i=1;i<=n;i++) maxn[i]=max(maxn[i],q_sum(1,lt[i],n+m)); for(int i=1;i<=n;i++) printf("%d %d\n",minx[i],maxn[i]); }
俺用莫隊做的 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<set> using namespace std; int N,CC[300005],rank[300005],tree[3000005],front[300005],Q,Size,ans,cs[300005],vis4[300005],p1[300005],n,m,vis1[300005],vis[300005][2],a[300005],p[300005]; int Max(int XXX,int YYY){ if(XXX<YYY) return YYY; return XXX; }struct Node{ int id,val; }cx1[300005]; int Cmp(Node q,Node w){ if(q.val==w.val) return q.id<w.id; return q.val<w.val; } struct node{ int l,r,num; }cx[300005]; int cmp(node XXX,node YYY){ if(XXX.l/Size==YYY.l/Size) return XXX.r<YYY.r; return XXX.l/Size<YYY.l/Size; } int del(int X){ cs[a[X]]--; if(cs[a[X]]==0) ans--; return 0; } int add(int X){ if(cs[a[X]]==0) ans++; cs[a[X]]++; return 0; } void insert(int po,int d){ for(;po<=N;po+=po&-po) tree[po]+=d; } int query(int po){ int sum=0; for(;po;po-=po&-po) sum+=tree[po]; return sum; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d",&a[i]); vis1[a[i]]++; vis[a[i]][0]=1; p[a[i]]=1; } for(int i=1;i<=n;i++) p[i]+=p[i-1]; for(int i=1;i<=m;i++){ if(vis1[a[i]]==1){ if(i!=m){ cx[++Q].l=i+1; cx[Q].r=m; cx[Q].num=a[i]; } cx1[++N].val=a[i]; cx1[N].id=N; CC[N]=a[i]; } else{ if(vis4[a[i]]==0){ cx1[++N].val=a[i]; cx1[N].id=N; CC[N]=a[i]; front[a[i]]=i+1; vis4[a[i]]++; } else{ vis4[a[i]]++; if(vis4[a[i]]==vis1[a[i]]){ if(front[a[i]]!=i){ cx[++Q].l=front[a[i]]; cx[Q].r=i-1; cx[Q].num=a[i]; } front[a[i]]=i+1; if(front[a[i]]!=m+1){ cx[++Q].l=front[a[i]]; cx[Q].r=m; cx[Q].num=a[i]; } } else{ if(front[a[i]]!=i){ cx[++Q].l=front[a[i]]; cx[Q].r=i-1; cx[Q].num=a[i]; front[a[i]]=i+1; } } } } } sort(cx1+1,cx1+1+N,Cmp); for(int i=1;i<=N;i++) rank[cx1[i].id]=i; for(int i=1;i<=N;i++){ insert(rank[i],1); vis[CC[i]][1]=CC[i]+i-query(rank[i]); } Size=(int)sqrt(m); sort(cx+1,cx+Q+1,cmp); int l=1,r=0; for(int i=1;i<=Q;i++){ int L=cx[i].l,R=cx[i].r; while(l<L) del(l++); while(l>L) add(--l); while(r<R) add(++r); while(r>R) del(r--); vis[cx[i].num][1]=Max(vis[cx[i].num][1],ans+1); } for(int i=1;i<=n;i++){ if(vis[i][0]!=1){ vis[i][0]=i; vis[i][1]=i+(p[n]-p[i]); } } for(int i=1;i<=n;i++){ printf("%d %d\n",vis[i][0],vis[i][1]); } }