• bzoj5092 分割序列


    题目链接

    problem

    对于一个长度为n的非负整数序列(b_1,b_2,...,b_n),定义这个序列的能量为:(f(b)=maxlimits_{i=0,1,...,n}(b_1 otimes b _2 otimes...otimes b_i)+(b_{i+1} otimes b_{i+2} otimes...otimes b_n)),给定一个长度为n的非
    负整数序列(a_1,a_2,...,a_n),请计算a的每个前缀的能量值。

    solution

    先对a求一边前缀异或和。然后对于前i个元素,从j位置分开的贡献就是(S_iotimes S_j+S_j)

    从高到低按位处理。如果(S_i)的第k位为1,那么无论(S_j)的第k位为0还是为1,造成的贡献都是(2^k)。如果(S_i)的第k位为0,那么如果在满足前面位置的限制的情况下,(S_j)的第k位可以为1,那么造成的贡献就是(2 imes 2^k)

    那么问题来了,当(S_i)的第k位为0时,如何判断前面是否有某个位置在满足前面限制的情况下当前位置为1呢?

    (f_i)表示i的超集出现的最靠前的位置。然后上面的判断就很好做了:只要看一下满足所有限制的最小位置是不是在i之前就可以了。

    因为是超集,所以(f_i)的预处理可以用(FMT)优化。复杂度(Theta(2^kk))

    总复杂度就是(Theta(nk+2^kk))

    code

    /*
    * @Author: wxyww
    * @Date:   2019-12-17 22:04:49
    * @Last Modified time: 2019-12-17 22:18:24
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 300100;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    int mi[N],mx,f[N * 10],a[N];
    int main() {
    	int n = read();
    	
    	memset(f,0x3f,sizeof(f));
    
    	for(int i = 1;i <= n;++i) {
    		a[i] = read() ^ a[i - 1];f[a[i]] = min(i,f[a[i]]);
    		mx = max(mx,a[i]);
    	}
    
    	mi[0] = 1;
    	for(int i = 1;i <= 30;++i) mi[i] = mi[i - 1] << 1;
    
    	for(int i = 0;i <= 20;++i) {
    		for(int j = 0;j <= mx;++j) {
    			if(!(j >> i & 1)) f[j] = min(f[j],f[j | (1 << i)]);
    		}
    	}
    
    	for(int i = 1;i <= n;++i) {
    		int now = 0;
    		ll ans = 0;
    		for(int k = 20;k >= 0;--k) {
    			if((a[i] >> k) & 1) ans += mi[k];
    			else if(f[now | (1 << k)] <= i) {
    				ans += 2ll * mi[k],now |= (1 << k);
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    1105 Spiral Matrix (25 分)螺旋矩阵
    1089 Insert or Merge (25 分)
    1044 Shopping in Mars (25 分)二分查找
    1068 Find More Coins (30 分)记忆化搜索
    1133 Splitting A Linked List (25 分)
    1145 Hashing
    1147 Heaps (30 分)
    1098 Insertion or Heap Sort (25 分)
    自测-3 数组元素循环右移问题 (20 分)
    自测-1 打印沙漏 (20 分)
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj5092.html
Copyright © 2020-2023  润新知