zoukankan      html  css  js  c++  java
  • Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)

    题面

    Bzoj

    洛谷

    题解

    考虑一个什么样的区间满足重组之后可以变成$3$的倍数。不妨设$tot$为一个区间内$1$的个数。如果$tot$是个偶数,则这个区间一定是$3$的倍数,接着考虑奇数的情况。

    如果只有$1$个$1$,那么无论如何都不行,只需考虑$3$个$1$的情况,因为其他的$1$可以看做偶数个$1$的情况。不难发现,当只有$3$个$1$的时候,我们需要有至少$2$个$0$,接着就可以用线段树来维护了。

    我们考虑记录三个数组,$sum[4][3], lx[4][3], rx[4][3]$,分别表示区间中的总的方案数,包含左端点的方案数,包含右端点的方案数。

    而对于后面的二维数组,第一位表示包含$1$的个数,分别表示有零个$1$,一个$1$,有偶数(大于$0$)个$1$,有奇数(大于$1$)个一

    二位表示$0$的个数,分别表示有零个$0$,一个$0$,以及两个及以上个$0$

    比如说$sum[2][1]$就是表示,当前区间中,包含有偶数个$1$,并且有且仅有一个$0$的子区间的个数。

    接着的难点就是写$pushup$了,可以参考代码。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::min; using std::max;
    using std::sort; using std::swap;
    typedef long long ll;
    
    template<typename T>
    void read(T &x) {
        int flag = 1; x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
        while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
    }
    
    const int N = 1e5 + 10;
    int n, m, x, l, r, opt, a[N];
    inline int get1(int x) { return (x <= 1) ? x : (x % 2 + 2); }
    inline int get0(int x) { return (x <= 1) ? x : 2; }
    struct Matrix {
    	ll cnt[2], sum[4][3], lx[4][3], rx[4][3];
    	Matrix operator + (const Matrix & a) const {
    		Matrix ret, lc = *this, rc = a;
    		ret.cnt[0] = lc.cnt[0] + rc.cnt[0];
    		ret.cnt[1] = lc.cnt[1] + rc.cnt[1];
    		for(int i = 0; i < 4; ++i)
    			for(int j = 0; j < 3; ++j) {
    				ret.sum[i][j] = lc.sum[i][j] + rc.sum[i][j];
    				ret.lx[i][j] = lc.lx[i][j], ret.rx[i][j] = rc.rx[i][j];
    			}
    		for(int i1 = 0; i1 < 4; ++i1)
    			for(int i0 = 0; i0 < 3; ++i0)
    				if(lc.rx[i1][i0]) {
    					ll x = lc.rx[i1][i0];
    					for(int j1 = 0; j1 < 4; ++j1)
    						for(int j0 = 0; j0 < 3; ++j0)
    							if(rc.lx[j1][j0]) {
    								ll y = rc.lx[j1][j0];
    								ret.sum[get1(i1 + j1)][get0(i0 + j0)] += x * y;
    							}
    				}
    		int lc0 = lc.cnt[0], lc1 = lc.cnt[1];
    		int rc0 = rc.cnt[0], rc1 = rc.cnt[1];
    		for(int i = 0; i < 4; ++i)
    			for(int j = 0; j < 3; ++j) {
    				ret.lx[get1(lc1 + i)][get0(lc0 + j)] += rc.lx[i][j];
    				ret.rx[get1(rc1 + i)][get0(rc0 + j)] += lc.rx[i][j];
    			}
    		return ret;
    	}
    } t[N << 2];
    
    inline void pushup(int o, int lc, int rc) { t[o] = t[lc] + t[rc]; }
    void build(int o = 1, int l = 1, int r = n) {
    	if(l == r) {
    		int x = (a[l] == 1), y = (a[l] == 0);
    		t[o].cnt[0] = y, t[o].cnt[1] = x;
    		t[o].sum[x][y] = t[o].lx[x][y] = t[o].rx[x][y] = 1;
    		return ;
    	} int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    	build(lc, l, mid), build(rc, mid + 1, r), pushup(o, lc, rc);
    }
    void modify(int k, int o = 1, int l = 1, int r = n) {
    	if(l == r) {
    		int x = t[o].cnt[1], y = t[o].cnt[0];
    		t[o].sum[x][y] = t[o].lx[x][y] = t[o].rx[x][y] = 0;
    		swap(t[o].cnt[0], t[o].cnt[1]);
    		t[o].sum[y][x] = t[o].lx[y][x] = t[o].rx[y][x] = 1;
    		return ;
    	} int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    	if(k <= mid) modify(k, lc, l, mid);
    	else modify(k, rc, mid + 1, r);
    	pushup(o, lc, rc);
    }
    Matrix query(int ql, int qr, int o = 1, int l = 1, int r = n) {
    	if(l >= ql && r <= qr) return t[o];
    	int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    	if(qr <= mid) return query(ql, qr, lc, l, mid);
    	else if(ql > mid) return query(ql, qr, rc, mid + 1, r);
    	else return query(ql, qr, lc, l, mid) + query(ql, qr, rc, mid + 1, r);
    }
    
    int main () {
    	read(n);
    	for(int i = 1; i <= n; ++i) read(a[i]);
    	read(m), build(); Matrix ans; ll ret;
    	while(m--) {
    		read(opt);
    		if(opt == 1) read(x), modify(x);
    		else {
    			read(l), read(r), ans = query(l, r), ret = 0;
    			ret = ans.sum[0][0] + ans.sum[0][1] + ans.sum[0][2]
    				+ ans.sum[2][0] + ans.sum[2][1] + ans.sum[2][2]
    				+ ans.sum[3][2];
    			printf("%lld
    ", ret);
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    iOS textField placeholder 信息上浮
    iOS 用keypath设置一些属性
    iOS 自由拖动的滑块
    iOS 系统字体和导入新字体
    iOS 无法联网
    iOS 视频启动界面
    iOS 动画分享
    Xcode8 打包ios app,上传APPStore,发布流程 以及证书和配置文件遇到的坑
    mac电脑怎么打开world文档的目录
    ios添加设备真机测试,以及"Undefined symbols for architecture x86_64:''错误
  • 原文地址:https://www.cnblogs.com/water-mi/p/10350483.html
Copyright © 2011-2022 走看看