1 条题解

  • 0
    @ 2026-9-24 22:12:23

    注意到数据范围达到了 10610^6,且内存较小,启发我们使用 O(n)O(n) 做法。

    考虑两个罪犯走的路径是什么样的,罪犯抢劫的房子是他走过的房子的子序列,两个罪犯的终点相同,起点颜色相同。

    思考罪犯开始时所在房子颜色相同这个怎么维护,我们记 pripr_i 表示与第 ii 个房子颜色相同的下标最大值。

    从贪心的角度考虑,只要保证一段路径两边有一对颜色相同的点对,这条路径存在起点,所以我们可以对 pripr_i 取前缀 max⁡\max。

    依旧从贪心的角度考虑,显然有左边的罪犯的第一个抢劫房子的下标越大越好,右边反之。

    接着考虑怎么维护子序列中第一个下标最值,不妨借鉴 LIS 的处理方法,因为每个罪犯对每种颜色的房子分别最多抢劫一次,可以直接把 xix_i 视为 ii 再用 LIS 处理。我们记 ltj,ilt_{j,i} 表示终点是 jj 号房子时第 xix_i 对应的 x1x_1 的下标最值,不难想到转移如下。

    当 cj=xi,i≠1c_j = x_i,i \ne 1 时,有 ltj,i=ltj−1,i−1lt_{j,i} = lt_{j-1,i-1}。

    当 cj=xi,i=1c_j = x_i,i = 1 时,有 ltj,i=jlt_{j,i} = j。

    因为 ltjlt_{j} 只与 ltj−1lt_{j-1} 有关,可以滚动。

    因为有两段路径,我们用 did_i 记录以 ii 为左边罪犯以 ii 号房子为终点的子序列中第一个下标最值。

    第二段倒着处理就行。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0,f=1;
    	char c=getchar();
    	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    	while(c>='0'&&c<='9') {x=(x*10)+c-'0';c=getchar();}
    	return x*f;
    }//快读
    const int N=1e6+5;
    int n,k,m,l,x[N],y[N],c[N],lt[N],pr[N],d[N];
    vector<int> ans;
    signed main(){
    	n=read(),k=read();
    	for(int i=1;i<=n;i++) {c[i]=read();lt[c[i]]=i;}
    	for(int i=1;i<=n;i++) pr[i]=max(pr[i-1],lt[c[i]]);
    	m=read(),l=read();
    	for(int i=1;i<=m;i++) x[i]=read(),y[x[i]]=i;//y[]用来存x[i]对应的下标
    	for(int i=1;i<=n;i++) lt[i]=0;
    	for(int i=1;i<=n;i++) {
    		if(c[i]==x[1]) lt[1]=i;
    		else lt[y[c[i]]]=lt[y[c[i]]-1];
    		if(lt[m]) d[i]=lt[m];//统计
    	}//第一段
    	memset(x,0,sizeof(x));memset(y,0,sizeof(y));
    	for(int i=1;i<=l;i++) x[i]=read(),y[x[i]]=i;
    	for(int i=1;i<=n;i++) lt[i]=0;//初始化
    	for(int i=n;i>=1;i--) {//倒着
    		if(c[i]==x[1]) lt[1]=i;
    		else lt[y[c[i]]]=lt[y[c[i]]-1];
    		if(lt[l]&&d[i]&&c[i]==x[l]) {
    			int z=d[i]-1,p=lt[l];
    			if(pr[z]>p) ans.push_back(i);//统计
    		}
    	}//第二段
    	printf("%d\n",(int)ans.size());
    	sort(ans.begin(),ans.end());
    	for(int x:ans) printf("%d ",x);
    	return 0;
    }
    
    • 1

    信息

    ID
    5493
    时间
    1000ms
    内存
    164MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者