P6360 [CEOI2018] Lottery 题解
P6360 [CEOI2018] Lottery 题解
集训时讲了这道题,来写一下题解当笔记。
思路
注意到这些区间有一个这样的性质:设
于是我们有这样的策略,先暴力算出所有的
代码
代码很短,重在思考(比赛时没有想到
#include <iostream>
#include <algorithm>
#define ll int
using namespace std;
const ll N=10002;
const ll Q=102;
inline ll read(){
register ll f=1,x=0;
register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
ll n,l,A[N],q,ans[N][Q];
ll chg[N],ask[N],lis[N];
int main(){
n=read(),l=read();
for(ll i=1;i<=n;i++) A[i]=read();
q=read();
for(ll i=1;i<=q;i++){
ask[i]=read();
lis[i]=ask[i];
}
sort(lis+1,lis+1+q);
ll nq=unique(lis+1,lis+1+q)-lis-1;
ll tp=1;
for(ll i=1;i<=n;i++){
while(tp<=nq&&i>lis[tp]) tp++;
chg[i]=tp;
}
for(ll i=2;i+l-1<=n;i++){
ll d=0;
for(ll j=0;j<l;j++) if(A[1+j]!=A[i+j]) d++;
ans[1][chg[d]]++,ans[i][chg[d]]++;
for(ll j=1;j+i<=n-l+1;j++){
d=d-(A[j]!=A[i+j-1])+(A[j+l]!=A[i+j-1+l]);
ans[1+j][chg[d]]++,ans[i+j][chg[d]]++;
}
}
for(ll i=1;i<=n-l+1;i++)
for(ll j=1;j<=nq;j++) ans[i][j]+=ans[i][j-1];
for(ll i=1;i<=q;i++){
for(ll j=1;j<=n-l+1;j++) printf("%d ",ans[j][chg[ask[i]]]);
printf("\n");
}
return 0;
}