一个环 有 2∗n+12∗n+1 个位置, 选择 nn 个位置填上// 个 AA 或 个 BB
….题目太长了 自己查吧qwq
有一点很容易想到就是把 和BB 一个看成 一个看成−1−1 空位看成 BB
然后枚举空位的位置为x 快速计算答案。
我们发现
对于 : sum[i]>sum[x]sum[i]>sum[x] 且 ii位置为 即可对答案有贡献
对于 i<xi<x : sum[n]−sum[x]+sum[i]>0sum[n]−sum[x]+sum[i]>0即可对答案有贡献
整理得:sum[i]>sum[x]+1sum[i]>sum[x]+1
可以数据结构维护这个拿到部分分。O(nlogn)O(nlogn)
然后我们发现 每个相邻的sum[x]sum[x]只差11。我们可以暴力记录下所有的sumsum 然后每次O(1)O(1)计算答案。
整体复杂度 O(n)O(n) 注意思考一下修改枚举过的sumsum数组值时应该新开数组记录。 即buccbucc。
#include <bits/stdc++.h>
using namespace std;
const int base=10000000;
int sum[20000010],p[20000010],buc[20000010],bucc[20000010];
int seed,n,k,S;
int getrand(){
seed=((seed*12321)^9999)%32768;
return seed;
}
void generateData(){
scanf("%d%d%d",&k,&seed,&S);
int t=0;
n=k*2+1;
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++)
{
p[i]=(getrand()/128)%2;
t+=p[i];
}
int i=1;
while(t>k)
{
while(p[i]==0)
i++;
p[i]=0;
t--;
}
while(t<k){
while(p[i]==1)
i++;
p[i]=1;
t++;
}
}
int ans=0,pos,pos2,pos3;
//sum[i]>sum[x]
//sum[n]-sum[x]+sum[i]>0
//sum[i]>sum[x]+1
//sum[]
int main(){
generateData();
for(int i=1;i<=n;i++)sum[i]=p[i]?sum[i-1]+1:sum[i-1]-1;
for(int i=1;i<=n;i++){
if(p[i]){
buc[sum[i]+base]++;
}
}
for(int i=2;i<=n;i++)
if(sum[i]>sum[1]&&p[i])ans++;
if(!p[1]&&ans==0)pos=1;
if(!p[1]&&ans==S)pos2=1;
if(p[1])buc[sum[1]+base]--,buc[sum[1]+base-1]++;
int now=sum[1]+base+1;
// puts("qwq");
for(int x=2;x<=n;x++){
// cout<<ans<<endl;
if(p[x]){
ans-=buc[now++];
buc[sum[x]+base]--,buc[sum[x]+base-1]++;
}
else {
ans+=buc[--now];
if(ans==0)pos=x;
else if(ans==S)pos2=x;
}
}
// cout<<ans<<endl;
//puts("qaq");
// sum[i]>sum[x]
// sum[n]-sum[x]+sum[i]>0
// sum[i]>sum[x]-1
ans=0;
memset(buc,0,sizeof(buc));
for(int i=1;i<=n;i++)sum[i]=p[i]?sum[i-1]-1:sum[i-1]+1;
for(int i=1;i<=n;i++){
if(!p[i]){
buc[sum[i]+base]++;
}
}
for(int i=2;i<=n;i++)
if(sum[i]>sum[1]&&(!p[i]))ans++;
if(!p[1]&&ans==S)pos3=1;
// for(int i=1;i<=20000005;i++)bucc[i]=buc[i];
// if(!p[1])bucc[sum[1]+base]--,bucc[sum[1]+base+1]++;
now=sum[1]+base+1;
// cout<<ans; 1 2 3 4 3 2 1 0 -1 0 1
for(int x=2;x<=n;x++){
// cout<<ans<<endl;
if(!p[x]){
ans-=buc[now++];
if(!p[x-1])buc[sum[x-1]+base]--,buc[sum[x-1]+base+1]++;
// bucc[sum[x]+base]--,bucc[sum[x]+base+1]++;
if(ans==S)pos3=x;
}
else {
ans+=buc[--now];
if(!p[x-1])buc[sum[x-1]+base]--,buc[sum[x-1]+base+1]++;
}
}
cout<<pos<<endl<<pos2<<endl<<pos3<<endl;
return 0;
}
//0 0 0 0 1 1 1 1 1 0 0