ARC 203
A
我不会柿子解法。
考虑二分,对于 \(x\) 的判定,一定是尽量平均的分到每一个人。然后,每一组的每一个全胜者在其他每一个组一定要匹配上一个非全胜者。求出这个组以外的非全胜者个数最小值就可以判定了。
B
\(A\rightarrow B\) 有点难做,因此套路的想要 \(A,B\) 都到达最小值然后判断是不是相等。对于 \(A\) 做这个算法即可,\(B\) 一样:
-
现在 \(0\sim i-1\) 都是 \(0\),目标把 \(i\) 从 \(1\) 变成 \(0\)。
-
找到一个 \(i+1\) 往后的 \(0\),如果没有 \(0\)吗,说明已经是
00...0011...11的形式,结束。否则可以找到一个 \(0\)。 -
如果能找到 \(0\) 使得后面是 \(1\),直接交换,归纳到子问题。
-
否则只能是前面有 \(1\) 的。如果前面的 \(1\) 不是 \(i\),可以先交换,交换后出现一个上面的情况。因此也是可以归纳下去的。
-
如果前面的 \(1\) 只能是 \(i\),说明 \(A\) 中只有一个 \(1\)。
那么对于 \(1\) 的个数 \(\ge 2\) 已经做完了。考虑只有一个的问题。
发现相同的边角是可以的,不同的边角是不行的,只有一个是边角是不行的,两个都不是边角是可以的。
C
重要:\(k\le h+w\)。记 \(r=(h(w-1)+w(h-1)-(h+w-2))\)。
-
\(k<h+w-2\):答案是 \(0\)。
-
\(k=h+w-2\):答案是 \(\binom{h+w-2}{h-1}\)。
-
\(k=h+w-1\):答案是 \(\binom{h+w-2}{h-1}\times r\)。即选择一条路径和不是路径上的一点。
-
\(k=h+w\)。有两种路径长度。
-
长度 \(h+w-2\)。\(\binom{h+w-2}{h-1}\times \binom{r}{2}\) 只在有两条不同路径的时候会统计两遍。这个会在有 \(2\times 2\) 被连接出现,那么压缩成 \(1\times 1\),在转化为在这个路径上选择一个扩大。因此减去 \(\binom{h+w-4}{h-2}\times (h+w-3)\)。
-
长度为 \(h+w\)。一定有一个竖着的往上走,两边都是横着的,或者一个横着的往左走,两边都是竖着的。现在只考虑第一种,第二种类似。考虑这个横竖横,整体折下去,变成一个往下的竖,再在这个里面选择一个不是边缘的竖变回去,相当于统计了答案。那么就是 \(h+1\) 个竖,\(w-3\) 个横。\(\binom{h+w-1}{w-3}\times (h-1)\)。
-
D
比起加入,删除更容易。加入有这几种情况:
-
\(00\rightarrow 000\)。
-
\(01\rightarrow 011\)。
-
\(10\rightarrow 110\)。
-
\(11\rightarrow 101\)。
那么可以得出,连续的 \(0\) 可以不超过 \(2\) 个,连续的 \(1\) 可以不超过 \(1\) 个(前提是边上有 \(0\)),并且 \(101\) 可以变成 \(11\)。
发现得到的 \(B\) 一定是 \(C(100100\cdots 100)D\),\(C,D\) 比较短,中间重复。
重复的次数是好求出来的。发现是 \(a_i=0,a_{i-1}=1,a_{i+1}=0\) 的 \(i\) 的个数。那么相应的可以求出对应的区间。
现在就是有两边,没有连续的 \(0\),求答案。分类讨论一下即可。
对于没有 \(100\) 的也要特殊判断。赛时代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5+5;
int n,q,a[N],cnt,is[N],ctok,bit[N];
set<int> st;
void M(int p,int v){
while (p<N){
bit[p]+=v,p+=p&-p;
}
}
int Q(int p){
int res=0;
while (p){
res+=bit[p],p-=p&-p;
}
return res;
}
void upd(int x){
if (x<=1 || x>=n) return;
if (a[x-1]==1 && a[x]==0 && a[x+1]==0){
ctok++,is[x]=1;
st.insert(x);
}
else{
if (is[x]) st.erase(x);
is[x]=0;
}
}
void fst(int x){
upd(x);
M(x,a[x]);
}
void mod(int x){
ctok-=is[x]+is[x-1]+is[x+1];
cnt+=(a[x]==1?-1:1);
if (a[x]==1) M(x,-1);
else M(x,1);
a[x]=a[x]^1;
upd(x),upd(x-1),upd(x+1);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (int i=1; i<=n; i++){
cin>>a[i];
cnt+=a[i];
}
for (int i=1; i<=n; i++){
fst(i);
}
cin>>q;
while (q--){
int x;
cin>>x;
mod(x);
if (cnt==0){
cout<<2<<"\n";
continue;
}
if (cnt==n){
cout<<n<<"\n";
continue;
}
int ans=ctok*3;
assert(ctok==(int)st.size());
if (ctok==0){
int tc=(a[1]==0 && a[2]==0);
if (a[1]==0 && a[n]==0 && cnt!=0){
cout<<3+tc<<"\n";
}
else
cout<<2+tc<<"\n";
continue;
}
int l=(*st.begin())-2;
int r=(*st.rbegin())+2;
// 1~l r~n
int lb=0,rb=l+1;
while (lb+1<rb){
int mid=lb+rb>>1;
if (Q(l)-Q(mid-1)==l-mid+1) rb=mid;
else lb=mid;
}
if (1<=l) l=lb;
lb=r-1,rb=n+1;
while (lb+1<rb){
int mid=lb+rb>>1;
if (Q(mid)-Q(r-1)==0) lb=mid;
else rb=mid;
}
if (r<=n) r=rb;
if (1<=l){
if (a[1]==0){
ans++;
if (2<=l && a[2]==0) ans++;
}
}
if (r<=n){
if (a[n]==1) ans++;
else ans+=min(2,n-r+1);
}
cout<<ans<<"\n";
}
return 0;
}
浙公网安备 33010602011771号