原题在此
某位大佬用线段树做的
#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,int ql,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]);
}
}