1. 程式人生 > >[CTSC2017]金鑰

[CTSC2017]金鑰

一個環 有 2n+1 個位置, 選擇 n 個位置填上//nAnB
….題目太長了 自己查吧qwq

有一點很容易想到就是把 AB 一個看成 1 一個看成1 空位看成 B
然後列舉空位的位置為x 快速計算答案。
我們發現
對於 i>x : sum[i]>sum[x]i位置為A 即可對答案有貢獻
對於 i<x : sum[n]sum[x]+sum[i]>0即可對答案有貢獻
整理得:

sum[i]>sum[x]+1
可以資料結構維護這個拿到部分分。O(nlogn)
然後我們發現 每個相鄰的sum[x]只差1。我們可以暴力記錄下所有Asum 然後每次O(1)計算答案。
整體複雜度 O(n) 注意思考一下修改列舉過的sum陣列值時應該新開陣列記錄。 即bucc

#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