题意
初始为 , 次操作把一个数提到最前面,最后输出每个数的最前位置和最后位置。
题解
最前位置就是初始位置或者
。
最后位置怎么得到呢?
我们可以发现就是算上从开始到第一次被提,和最后一次被提到结束,两次被提之间。求这之间的的不同种类数,但是第一个还要求大于自己的不同种类数。
不过我们可以简单的减小一下处理难度,在初始倒入插入一下,这样子就能保证比自己小的没有影响了。
这个时候莫队就可以解决了,
的复杂度。
或者采用第二种方法,模拟
在前面加
个
:
如果提一个
到前面,可以这样做:
这样就可以处理了,用树状数组求出在自己前面的数量,并且保存一下自己的当前位置。
根据上面的思考,每次只需要在提到前面前计算一下即可,以及最后结束的时候。
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
#define sf(x) scanf("%d",&x)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 600000+500;
const ll mod = 1e9+7;
int n,m;
int A[maxn],num[maxn],pos[maxn];
int Mi[maxn],Mx[maxn];
vector<int>G[maxn];
int L=1,R=1,block,ret;
inline void add(int x){
num[x]++;
if(num[x]==1)ret++;
}
inline void del(int x){
num[x]--;
if(num[x]==0)ret--;
}
struct node{
int l,r,index;
friend bool operator < (node a,node b){
if(pos[a.l]!=pos[b.l])return a.l<b.l;
else{
if(pos[a.l]&1)return a.r<b.r;
else return a.r>b.r;
}
}
}Q[1000050];
int main(){
cin>>n>>m;
FOR(i,1,n)A[i]=n-i+1,Mi[i]=Mx[i]=i;
FOR(i,1,m)sf(A[n+i]),Mi[A[n+i]]=1;
block=sqrt(n+m);
FOR(i,1,n+m)pos[i]=(i-1)/block+1;
FOR(i,1,n+m)G[A[i]].push_back(i);
int num=0;
FOR(i,1,n){
for(int j=1;j<G[i].size();j++){
++num;Q[num].l=G[i][j-1]+1,Q[num].r=G[i][j]-1;
Q[num].index=i;
if(Q[num].l>Q[num].r)--num;
}
++num;Q[num].l=G[i][G[i].size()-1]+1,Q[num].r=n+m;
Q[num].index=i;
if(Q[num].l>Q[num].r)--num;
}
//FOR(i,1,num)cout<<Q[i].l<<" "<<Q[i].r<<endl;
sort(Q+1,Q+1+num);
add(A[1]);
FOR(i,1,num){
while(L>Q[i].l){L--;add(A[L]);}
while(L<Q[i].l){del(A[L]);L++;}
while(R<Q[i].r){R++;add(A[R]);}
while(R>Q[i].r){del(A[R]);R--;}
Mx[Q[i].index]=max(Mx[Q[i].index],ret+1);
}
FOR(i,1,n)printf("%d %d\n",Mi[i],Mx[i]);
}
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
#define sf(x) scanf("%d",&x)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 600000+500;
const ll mod = 1e9+7;
int n,m;
int A[maxn],C[maxn];
int Mi[maxn],Mx[maxn],pos[maxn];
int lowbit(int x){return (x&(-x));}
void change(int x,int d){
for(int i=x;i<=maxn;i+=lowbit(i))C[i]+=d;
}
int query(int x){
if(x==0)return 0;
int ret=0;
for(int i=x;i;i-=lowbit(i))ret+=C[i];
return ret;
}
int main(){
cin>>n>>m;
FOR(i,1,n)pos[i]=m+i,Mi[i]=i,Mx[i]=i;
FOR(i,1,m)sf(A[i]);
FOR(i,1,n)change(pos[i],1);
//FOR(i,1,n)cout<<query(m+i)<<endl;
FOR(i,1,m){
int tmp=query(pos[A[i]]);
//cout<<pos[A[i]]-1<<" "<<tmp<<endl;;
Mx[A[i]]=max(Mx[A[i]],tmp);
Mi[A[i]]=min(Mi[A[i]],1);
change(pos[A[i]],-1);
pos[A[i]]=m-i+1;
change(pos[A[i]],1);
}
FOR(i,1,n){
int tmp=query(pos[i]);
Mx[i]=max(Mx[i],tmp);
}
FOR(i,1,n)printf("%d %d\n",Mi[i],Mx[i]);
}