1 条题解

  • 0
    @ 2026-5-6 15:46:34

    假设选择 [1,l][1,l][r,n][r,n] 的人,当 ll 向后移动的时候,rr 不可能向左移动,所以我们可以使用双指针解决。

    维护一个队伍个数 cntcnt,对于一个 ll,若 l+nr+1>cntl+n-r+1>cnt,即人数大于队伍数,则 rr 不合法,需要向后移动。

    维护一个桶,每一次移动 llrr 的时候更新一下。如果加入一个元素前桶该位置为空,或删除一个元素后桶该位置为空,就要更新 cntcnt

    注意 ll 要从 00 开始,rr11 开始。然后有一个 corner-case,就是 rr 跳出 nn 的范围,但 [1,l][1,l] 是合法的,此时也要更新答案。

    #include<bits/stdc++.h>
    #define int long long
    #define R(x) x=read()
    using namespace std;
    inline int read() {
    	int x=0,y=1;
    	char e=getchar();
    	while(e<'0'||e>'9') {
    		if(e=='-')y=-1;
    		e=getchar();
    	}
    	while(e>='0'&&e<='9') {
    		x=(x<<1)+(x<<3)+(e^'0');
    		e=getchar();
    	}
    	return x*y;
    }
    const int N=500005;
    int m,n,a[N];
    int t[N];
    signed main() {
    	R(m),R(n);
    	for(int i=1;i<=n;++i){
    		R(a[i])+1;
    		++t[a[i]];
    	}
    	t[0]=114;
    	int mx=0,cnt=m;
    	pair<int,int>ans={0,0};
    	for(int l=0,r=1;l<=n;){
    		while(r<=n&&l+n-r+1>cnt){
    			--t[a[r]];
    			if(!t[a[r]]) --cnt;
    			++r;
    		}
    		if(r==n+1&&cnt==l&&l>mx){
    			mx=l;
    			ans={l+1,n};
    		}
    		if(r<=n&&l+n-r+1>mx){
    			ans={l+1,r-1};
    			mx=l+n-r+1;
    		}
    		++l;
    		if(!t[a[l]])++cnt;
    		++t[a[l]];
    	}	
    	cout<<ans.first-1<<" "<<ans.second-1;
    	return 0;
    }
    
    • 1

    信息

    ID
    10182
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者