nomura2020_e Binary Programming

nomura2020_e Binary Programming

https://atcoder.jp/contests/nomura2020/tasks/nomura2020_e

NjKAB9.png

Tutorial

https://img.atcoder.jp/nomura2020/editorial.pdf

反向考虑,初始串为(T),每次删除一个字符.

发现所有的0都在1之前删除,考虑如果要删除一个1,那么删除它旁边的1是等价的,如果它旁边有0,那么删除0和它对于后面部分的奇偶性影响相同,而保留1不会更差.

如果只剩下1,那么依次删除即可,考虑0的删除顺序

对于连续的1,若长度为偶数,那么无论开始位置,它对于当前局面的贡献都是一样的,所以可以无视,对于奇数的1,类似的,可以变成只有一个1的情况.

那么一个局面就可以被描述为(a_0,a_1,cdots,a_k),表示开始有(a_0)个0,之后一个1,然后(a_1)个0,...

考虑每个1贡献的上界,对于第(i)个1,(sum_{j<i} a_j)的大约一半(根据奇偶性是个定值),是它一定会有的贡献,(sum_{jge i}) 是它可能会有的贡献,考虑这个上界是可以达到的.

可以如此构造,先删去所有(a_0)中的0,然后在(a_1)中保留一个0,其余删除,...,(a_k)中保留一个(0),其余删除,然后从后向前删去所有剩余的0.

Code

#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
int n,k; char T[maxn];
vector<int> a[maxn];
namespace seg {
	const int maxnode=maxn<<2;
	int sum[maxnode][2];
	bool rev[maxnode];
	inline void rever(int u) {
		rev[u]^=1;
		swap(sum[u][0],sum[u][1]);
	}
	inline void pushdown(int u) {
		if(rev[u]) {
			rever(u<<1);
			rever(u<<1|1);
			rev[u]=0;
		}
	}
	inline void pushup(int u) {
		sum[u][0]=sum[u<<1][0]+sum[u<<1|1][0];
		sum[u][1]=sum[u<<1][1]+sum[u<<1|1][1]; 
	}
	void build(int u,int l,int r) {
		if(l==r) {
			sum[u][l&1]=T[l]-'0';
			return;
		}
		int mid=(l+r)>>1;
		build(u<<1,l,mid);
		build(u<<1|1,mid+1,r);
		pushup(u);
	}
	void update(int u,int l,int r,int qp) {
		if(l==r) {
			sum[u][0]=sum[u][1]=0;
			return;
		}
		pushdown(u);
		int mid=(l+r)>>1;
		if(qp<=mid) update(u<<1,l,mid,qp);
		else update(u<<1|1,mid+1,r,qp);
		pushup(u);
	}
	void update(int u,int l,int r,int ql,int qr) {
		if(l==ql&&r==qr) {
			rever(u);
			return;
		}
		pushdown(u);
		int mid=(l+r)>>1;
		if(qr<=mid) update(u<<1,l,mid,ql,qr);
		else if(ql>mid) update(u<<1|1,mid+1,r,ql,qr);
		else {
			update(u<<1,l,mid,ql,mid);
			update(u<<1|1,mid+1,r,mid+1,qr);
		}
		pushup(u);
	}
}
int main() {
	scanf("%s",T+1),n=strlen(T+1);
	for(int i=1;i<=n;++i) {
		if(T[i]=='0') a[k].push_back(i);
		else {
			if(T[i+1]=='1') {++i; continue;}
			++k;
		}
	}
	if(a[k].size()) ++k;
	vector<int> ord;
	for(int i=0;i<k;++i) {
		for(int j=bool(i);j<a[i].size();++j) ord.push_back(a[i][j]);
	}
	for(int i=k-1;i>0;--i) {
		ord.push_back(a[i][0]);
	}
	for(int i=1;i<=n;++i) if(T[i]=='1') ord.push_back(i);
	seg::build(1,1,n);
	ll an=0;
	for(int i=0;i<ord.size();++i) {
		int x=ord[i];
		an+=seg::sum[1][1];
		seg::update(1,1,n,x);
		seg::update(1,1,n,x,n);
	}
	printf("%lld
",an);
	return 0;
}
原文地址:https://www.cnblogs.com/ljzalc1022/p/13232353.html