题解:P3570 [POI 2014] PRZ-Criminals
前言
怎么翻译题面不带数据范围的。
这个有紫吗?
Solution
考虑枚举两个人初始的位置,显然应该是某个颜色第一次出现和最后一次出现的位置最优。
现在考虑左侧的人从
因为保证走过的所有关键颜色不同,所以我们对每个位置而言,找到在关键颜色序列上的下一个关键颜色,建一个指针指向下一个关键颜色在当前位置之后第一次出现的位置。
现在
右侧的人同理,最后走到的区间就是可能的答案集合。
复杂度
Code
:::success[代码]
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fll
using namespace std;
int n,m;
int a[1000010];
int color_begin[1000010],color_end[1000010];
int k1,k2;
int p1[1000010],p2[1000010];
int bkt[1000010];
int nxt_color[1000010];
int nxt[1000010],prv[1000010];
int L[1000010],R[1000010];
static inline int findnxt(int x){while(x!=nxt[x]) x=nxt[x]=nxt[nxt[x]];return x;}
static inline int findprv(int x){while(x!=prv[x]) x=prv[x]=prv[prv[x]];return x;}
int val[1000010];
int main(){
cin.tie(0)->sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) color_end[a[i]]=i;
for(int i=n;i>=1;i--) color_begin[a[i]]=i;
cin>>k1>>k2;
for(int i=1;i<=k1;i++) cin>>p1[i];
for(int i=1;i<=k2;i++) cin>>p2[i];
for(int i=0;i<=m;i++) nxt_color[i]=0,bkt[i]=n+1;
for(int i=1;i<=k1;i++) nxt_color[p1[i]]=p1[i+(i!=k1)];
nxt[n+1]=n+1;
for(int i=n;i>=1;i--){
bkt[a[i]]=i,nxt[i]=bkt[nxt_color[a[i]]];
L[i]=findnxt(bkt[p1[1]]);
}
for(int i=0;i<=m;i++) nxt_color[i]=0,bkt[i]=0;
for(int i=1;i<=k2;i++) nxt_color[p2[i]]=p2[i+(i!=k2)];
prv[0]=0;
for(int i=1;i<=n;i++){
bkt[a[i]]=i,prv[i]=bkt[nxt_color[a[i]]];
R[i]=findprv(bkt[p2[1]]);
}
for(int i=1;i<=m;i++) if(color_begin[i]){
int l=color_begin[i],r=color_end[i];
if(l+1<=r-1&&L[l+1]<=R[r-1]) val[L[l+1]]++,val[R[r-1]+1]--;
}
vector<int> ans;
for(int i=1,nowv=0;i<=n;i++){
nowv+=val[i];
if(nowv&&a[i]==p1[k1]) ans.push_back(i);
}
cout<<ans.size()<<"\n";
for(int x:ans) cout<<x<<" ";
cout<<"\n";
# ifdef TakanashiHoshino
cerr<<"\n\033[1;38;2;234;200;225mUsed time: "<<clock()*1.0/CLOCKS_PER_SEC<<"s.\033[0m\n";
# endif
return 0;
}
:::