感觉自己的解法有点歪
/* 每次把一个数提到最前面,问整个过程结束后1..n每个数出现最靠前的位置和最靠后的位置 最靠前:如果一个数被提前过,那么必然是1 如果从来没被提前过,就是其原来的位置 最靠后:维护数i每次被提前的时间序列time[i][] time[i][1]到time[i][2]之间出现不同元素的个数就是其在这一段时间内i最靠后的位置 i出现的最靠后位置就是所有这种位置取max,再和初始值取max */ #include<bits/stdc++.h> using namespace std; #define N 600005 int n,m,a[N],Max[N],flag[N],Min[N]; vector<int>times[N]; int q,block; struct Query{ int l,r,col; }Q[N]; int cmp(Query a,Query b){ if(a.l/block == b.l/block)return a.r<b.r; return a.l<b.l; } int cnt[N],tot; void add(int x){ cnt[a[x]]++; if(cnt[a[x]]==1)tot++; } void del(int x){ cnt[a[x]]--; if(!cnt[a[x]])tot--; } int c[N],vis[N]; void update(int x){ while(x<=n){ c[x]++; x+=x&-x; } } int query(int x){ int res=0; while(x){ res+=c[x]; x-=x&-x; } return res; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++)Max[i]=Min[i]=i; for(int i=1;i<=m;i++){ cin>>a[i]; flag[a[i]]=1; } for(int i=1;i<=n;i++)if(flag[i])Min[i]=1; for(int i=1;i<=m;i++){//每个数前有多少比其大的 if(vis[a[i]])continue; vis[a[i]]=1; Max[a[i]]+=query(n)-query(a[i]); update(a[i]); } for(int i=1;i<=n;i++) if(!vis[i]){ Max[i]+=query(n)-query(i); } for(int i=1;i<=m;i++)times[a[i]].push_back(i); for(int i=1;i<=n;i++)times[i].push_back(m+1); for(int i=1;i<=n;i++){ for(int j=0;j<times[i].size()-1;j++){ int l=times[i][j]+1,r=times[i][j+1]-1; if(l<=r){ ++q;Q[q].l=l;Q[q].r=r;Q[q].col=i; } } } block=sqrt(m); sort(Q+1,Q+1+q,cmp); int L=1,R=0; for(int i=1;i<=q;i++){ while(L>Q[i].l)add(--L); while(R<Q[i].r)add(++R); while(L<Q[i].l)del(L++); while(R>Q[i].r)del(R--); Max[Q[i].col]=max(tot+1,Max[Q[i].col]); } for(int i=1;i<=n;i++)cout<<Min[i]<<" "<<Max[i]<<' '; }