一个环 有
2∗n+1
2
∗
n
+
1
个位置, 选择
n
n
个位置填上// 个
A
A
或 个
B
B
….题目太长了 自己查吧qwq
有一点很容易想到就是把 和
B
B
一个看成 一个看成
−1
−
1
空位看成
B
B
然后枚举空位的位置为x 快速计算答案。
我们发现
对于 :
sum[i]>sum[x]
s
u
m
[
i
]
>
s
u
m
[
x
]
且
i
i
位置为 即可对答案有贡献
对于
i<x
i
<
x
:
sum[n]−sum[x]+sum[i]>0
s
u
m
[
n
]
−
s
u
m
[
x
]
+
s
u
m
[
i
]
>
0
即可对答案有贡献
整理得:
sum[i]>sum[x]+1
s
u
m
[
i
]
>
s
u
m
[
x
]
+
1
可以数据结构维护这个拿到部分分。
O(nlogn)
O
(
n
l
o
g
n
)
然后我们发现 每个相邻的
sum[x]
s
u
m
[
x
]
只差
1
1
。我们可以暴力记录下所有的
sum
s
u
m
然后每次
O(1)
O
(
1
)
计算答案。
整体复杂度
O(n)
O
(
n
)
注意思考一下修改枚举过的
sum
s
u
m
数组值时应该新开数组记录。 即
bucc
b
u
c
c
。
#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