zoukankan      html  css  js  c++  java
  • BZOJ4300: 绝世好题

    题目链接

    走这里

    题目分析

    确实是绝世好题
    喵?为什么大家都觉得是个裸DP……
    _(:з」∠)_可能是我tcl,有了(O(n^2))的解之后一直没搞出优化到(log)级别的办法,最后还是看了博客

    先说一下第一眼能得到的方程
    (dp[i] = max(dp[j] + (a[i] & a[j] != 0) (1 <= j <= i))
    但是发现这个玩意是(O(n^2))的,考虑如何优化
    考虑什么时候两个数按位与的结果不是(0),显然只要有一位上它们俩都是(1)就可以了,所以我们另外记录一个数组(mx[j]),表示处理到现在所有二进制下第(j)位是1的(a[k](1 <= k <= i))对应的(dp[i])的最大值
    那么重新得到一个状态转移方程:
    $dp[i] = max(mx[j]) + 1 (a[i]二进制表示下第j位是1) ( 因为)a_i <= 2 * 10 ^ 9(,所以我们的)j(只需要枚举到31即可 时间复杂度)O(nloga)$

    代码

    #include <bits/stdc++.h>
    #define N (200000 + 10)
    using namespace std;
    inline int read() {
    	int cnt = 0, f = 1; char c = getchar();
    	while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    	while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
    	return cnt * f;
    }
    int n, a[N], dp[N], mx[100];
    int ans = -1;
    int main() {
    	n = read();
    	for (register int i = 1; i <= n; i++) a[i] = read();
    	dp[1] = 1;
    	for (register int i = 1; i <= n; i++){
    		for (register int j = 0; j <= 31; j++) 
    			if (a[i] & (1 << j)) dp[i] = max(dp[i], mx[j] + 1);
    		for (register int j = 0; j <= 31; j++)
    			if (a[i] & (1 << j)) mx[j] = max(dp[i], mx[j]);
    		ans = max (ans, dp[i]);
    	}
    	printf("%d", ans);
    	return 0;
    }
    
  • 相关阅读:
    mysql递归层次查询
    mybatis+spring事务
    浅谈数据库表的分割技术(水平、垂直、库表散列)(引用)
    高并发的常见思维
    jee websocket搭建总结
    hibernate 多表查询
    jsp作为服务端,ajax请求回应
    排序(2)--希尔,快速,归并
    排序(1)--冒泡,插入,选择
    Java反射基础
  • 原文地址:https://www.cnblogs.com/kma093/p/11301900.html
Copyright © 2011-2022 走看看