zoukankan      html  css  js  c++  java
  • 【题解】 CF1327F AND Segments dp+按位

    Legend

    Link ( extrm{to Codeforces})

    现有一个长 (n) 的数组 (a (0 le a < 2^k)),给定 (m) 个限制,形如 (l,r,x) 表示 (operatorname{AND}limits_{i=l}^{r} a_i=x)

    求出有多少个满足条件的数组。

    (1 le n le 5cdot 10^5)(0 le m le 5cdot 10^5)(1 le k le 30)

    Editorial

    容易发现位之间答案独立,最后只需要乘起来,问题转化为 (a_i,xin{0,1})

    对于 (x=1) 的限制,等价于直接确定了这个区间一定都是 (1)

    对于 (x=0) 的限制,说明这个区间至少有一个 (0)

    只有 (x=0) 的限制时,是个经典题。

    做法是设 (dp_i) 表示只考虑前 (i) 个位置,第 (i) 个位置放了 (0),使得区间左端点 (le i) 的区间全部满足要求的方案数量。

    转移就直接找可行的转移点(右端点 (<i) 的区间的最靠右的左端点以后的位置都可行),一定是连续的区间 (sum) 一下就行了。

    前缀和可以动态维护,做到 (O(1)) 转移。

    在此处有了 (x=1) 的限制则直接钦定这些地方的 (dp) 值为 (0) 即可。

    复杂度 (O(k(n+m)))

    Code

    #include <bits/stdc++.h>
    
    #define LL long long
    
    using namespace std;
    
    const LL MOD = 998244353;
    const int MX = 5e5 + 233;
    
    int read(){
    	char k = getchar(); int x = 0;
    	while(k < '0' || k > '9') k = getchar();
    	while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
    	return x;
    }
    
    int n ,k ,m;
    struct segment{
    	int l ,r ,x;
    	bool operator <(const segment &B)const{
    		return r == B.r ? l > B.l : r < B.r;
    	}
    }s[MX];
    
    LL ban[MX] ,S[MX] ,dp[MX];
    LL solve(int bit){
    	for(int i = 1 ; i <= n + 1 ; ++i) ban[i] = 0;
    	for(int i = 1 ; i <= m ; ++i){
    		if((s[i].x >> bit) & 1){
    			ban[s[i].l]++;
    			ban[s[i].r + 1]--;
    		}
    	}
    	int sl = 1 ,lim = 0;
    	dp[0] = S[0] = 1;
    
    	for(int i = 1 ; i <= n + 1 ; ++i){
    		ban[i] += ban[i - 1];
    		
    		while(sl <= m && s[sl].r < i){
    			if(((s[sl].x >> bit) & 1) == 0){
    				lim = max(lim ,s[sl].l);
    			}
    			++sl;
    		}
    
    		if(ban[i]) dp[i] = 0;
    		else if(lim) dp[i] = (S[i - 1] - S[lim - 1] + MOD) % MOD;
    		else dp[i] = S[i - 1];
    		S[i] = (S[i - 1] + dp[i]) % MOD;
    	}
    	return dp[n + 1];
    }
    
    int main(){
    	n = read() ,k = read() ,m = read();
    	for(int i = 1 ; i <= m ; ++i){
    		s[i].l = read() ,s[i].r = read() ,s[i].x = read();
    	}
    	LL Ans = 1;
    	sort(s + 1 ,s + 1 + m);
    	for(int i = 0 ; i < k ; ++i){
    		Ans = Ans * solve(i) % MOD;
    	}
    	cout << Ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    257. Binary Tree Paths
    324. Wiggle Sort II
    315. Count of Smaller Numbers After Self
    350. Intersection of Two Arrays II
    295. Find Median from Data Stream
    289. Game of Life
    287. Find the Duplicate Number
    279. Perfect Squares
    384. Shuffle an Array
    E
  • 原文地址:https://www.cnblogs.com/imakf/p/13734282.html
Copyright © 2011-2022 走看看