E. Messenger Simulator(莫队 区间不同的数个数 想法)

http://codeforces.com/contest/1288/problem/E

题意:

给出一个序列1到n,现在有m次操作,每次将一个数提到序列首。问每个数的最大位置和最小位置。

解析:

最小位置:被提过为1,否则为起始位置

最大位置:

先看 P P i i 次提到队首和第 i + 1 i+1 次,显然此时可能产生的最大值为:操作序列两个位置中间出现的所有其他数的种数,即区间不同数的个数。

P P 在第一次被提到队首之时的最大位置为: P + P+ 操作序列中之前出现过的大于 P P 的数量。

假设初始序列为 1 , 2 , 3 , 4 1,2,3,4 ,操作序列为 4 , 1 , 3 , 2 , 1 4,1,3,2,1 ,那么对于3来说,就是3(原来位置)+1(操作3之前操作过4)

这个相当于不算小于 P P 的数的:区间不同数的个数,这个怎么做?我们可以这样:操作序列变为 4 , 3 , 2 , 1 a p p e n d 4 , 1 , 3 , 2 , 1 4,3,2,1 -append-4,1,3,2,1 ,这样默认将小于 P P 的算且只算一次。此时的3的答案为 3 , 2 , 1 , 4 , 1 , 3 = 4 |3,2,1,4,1,3|=4

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-01-13-19.12.30
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=1e6+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

int a[maxn];
int mx[maxn],mi[maxn];
vector<int>V[maxn];

int K;
int idx(int pos){return pos/K; }
struct node{
    int l,r,id;
    bool operator<(const node &a)const{
        return idx(l)<idx(a.l)||idx(l)==idx(a.l)&&r<a.r;
    }
}q[maxn];

int times[maxn];

int main(){
    int n=rd,m=rd;
    K=sqrt(n+m);
    rep(i,1,n)mi[i]=i,mx[i]=i;
    rep(i,1,n)a[i]=n-i+1,V[a[i]].pb(i);
    rep(i,1,m){
        a[i+n]=rd;
        mi[a[i+n]]=1;
        V[a[i+n]].pb(i+n);
    }
    rep(i,1,n)V[i].pb(n+m+1);
    int cnt=0;
    rep(i,1,n){
        if(V[i].size()>1){
            rep(j,1,V[i].size()-1){
                if(V[i][j-1]+1<V[i][j]){
                    q[++cnt].id=i;
                    q[cnt].l=V[i][j-1]+1;
                    q[cnt].r=V[i][j]-1;
                    //debug(q[cnt].id<<" "<<q[cnt].l<<" "<<q[cnt].r);
                }
            }
        }
    }
    sort(q+1,q+1+cnt);
    int L=q[1].l,R=q[1].l-1;
    int kinds=0;
    rep(i,1,cnt){
        while(R<q[i].r)if((times[a[++R]]++)==0)kinds++;
        while(L>q[i].l)if((times[a[--L]]++)==0)kinds++;
        while(R>q[i].r)if((--times[a[R--]])==0)kinds--;
        while(L<q[i].l)if((--times[a[L++]])==0)kinds--;
        //debug(q[i].l<<" "<<q[i].r<<" "<<kinds);

        mx[q[i].id]=max(mx[q[i].id],kinds+1);
    }
    rep(i,1,n)
        printf("%d %d\n",mi[i],mx[i]);
}





发布了723 篇原创文章 · 获赞 314 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104005550