cf1121d 尺取
尺取,写起来有点麻烦
枚举左端点,然后找到右端点,,使得区间[l,r]里各种颜色花朵的数量满足b数组中各种花朵的数量,然后再judge区间[l,r]截取出后能否可以供剩下的n-1个人做花环
/* 给定序列A,分成n段,每段k个, 然后删掉A中的一些,但任要能组成n段,使得A中的一段包含序列B中的所有元素 如果可以输出删掉的元素,否则输出-1 */ #include<bits/stdc++.h> using namespace std; #define maxn 500005 int m,k,n,s,a[maxn],b[maxn],c[maxn]; int tot[maxn],cnt[maxn];//tot[i]表示第i种颜色需要的数量 int l,r,sum,Max,all; int judge(int l,int r){//判断除去l,r是否可行 int tmp1=l-1,tmp2=m-r; if(tmp1/k+tmp2/k+1>=n)return 1; return 0; } void add(int i){ if(cnt[a[i]]==0)return; tot[a[i]]++; if(tot[a[i]]==cnt[a[i]])sum++; } void del(int i){ if(cnt[a[i]]==0)return; tot[a[i]]--; if(tot[a[i]]==cnt[a[i]]-1)sum--; } int main(){ cin>>m>>k>>n>>s; for(int i=1;i<=m;i++)cin>>a[i],Max=max(Max,a[i]); for(int i=1;i<=s;i++)cin>>b[i],Max=max(Max,b[i]); for(int i=1;i<=s;i++)cnt[b[i]]++; l=1,r=k;sum=0; for(int i=1;i<=Max;i++) if(cnt[i]!=0)all++; for(int i=l;i<=k;i++) add(i); while(1){ if(sum==all){ if(judge(l,r)){//可行 vector<int>v; v.clear(); int tmp=r-l+1; for(int i=l;i<=r;i++){ if(cnt[a[i]]>0 || tmp==k) cnt[a[i]]--; else v.push_back(i),tmp--; } printf("%d\n",v.size()); for(int i=0;i<v.size();i++) printf("%d ",v[i]); return 0; } del(l);l++; } while(sum<all || l+k-1>r){ r++; if(r>m)break; add(r); } if(r>m)break; } puts("-1"); }