zoukankan      html  css  js  c++  java
  • [HDOJ

    题目链接:HDOJ - 5208

    题目分析

    使用按位贪心的思想,即从高位向低位枚举,尽量使这一位的答案为 1 。

    我们使用 DFS ,每次就是对于  [l1, r1] [l2, r2] x  进行处理,其中,x 是当前处理的最高位的权值,即 2^i 。

    如果 A 和 B 两人的区间的最高位都确定了,那就记录这一位的答案,直接处理下一位。

    如果 A 可以取 0/1 ,而 B 已经确定了,那么 A 就一定要取与 B 相反的那个。

    如果 A 和 B 都能取 0/1 ,那么我们就要分支进行 DFS ,一种是 A-1 B-1 ,另一种是 A-0 B-0 ,然后取这两种情况答案的较大值。

    然而剪枝是十分有效的,必须加上“如果 B 的区间完全包含了 A 的区间,直接返回 0”。不加这句就会 TLE 。(这样能将大部分分支剪掉?)

    另外,如果当前的区间是 [l, r]    l < x && r >= x

    那么最高位就可以选 0 也可以选 1。

    如果决策选 0 ,那么到下一位的区间就变为 [l, x - 1] 。

    如果决策选 1 ,那么到下一位的区间就变为 [x, r - x]。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    inline int gmax(int a, int b) {return a > b ? a : b;}
    
    int Ans, l, r, ll, rr, T;
    
    int Solve(int l, int r, int ll, int rr, int x)
    {
    	if (x == 0 || (ll <= l && rr >= r)) return 0;
    	int v, vv;
    	if (r < x) v = 0;
    	else if (l >= x) v = 1;
    	else v = 2;
    	if (rr < x) vv = 0;
    	else if (ll >= x) vv = 1;
    	else vv = 2;
    	if (v == 0)
    	{
    		if (vv == 0) // A-0 B-0
    			return Solve(l, r, ll, rr, x >> 1);
    		else if (vv == 1) // A-0 B-1
    			return x + Solve(l, r, ll - x, rr - x, x >> 1);
    		else // A-0 B-0-1
    			return Solve(l, r, ll, x - 1, x >> 1);
    	}
    	else if (v == 1)
    	{
    		if (vv == 0) // A-1 B-0
    			return x + Solve(l - x, r - x, ll, rr, x >> 1);
    		else if (vv == 1) // A-1 B-1
    			return Solve(l - x, r - x, ll - x, rr - x, x >> 1);
    		else // A-1 B-0-1
    			return Solve(l - x, r - x, 0, rr - x, x >> 1);
    	}
    	else
    	{
    		if (vv == 0) // A-0-1 B-0
    			return x + Solve(0, r - x, ll, rr, x >> 1);
    		else if (vv == 1) // A-0-1 B-1
    			return x + Solve(l, x - 1, ll - x, rr - x, x >> 1);
    		else // A-0-1 B-0-1
    			return gmax(Solve(l, x - 1, ll, x - 1, x >> 1), Solve(0, r - x, 0, rr - x, x >> 1));
    	}
    }
    
    int main()
    {
    	scanf("%d", &T);
    	for (int Case = 1; Case <= T; ++Case)
    	{
    		scanf("%d%d%d%d", &l, &r, &ll, &rr);
    		Ans = Solve(l, r, ll, rr, 1 << 30);
    		printf("Case #%d: %d
    ", Case, Ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JS设计模式(11)中介者模式
    PHP实现微信模板消息发送给指定用户
    PHP浮点精度问题
    PHP微信红包生成算法的程序源码(用抛物线的模型实现)
    PHP队列的实现详细操作步骤
    PHP数组函数实现栈与队列的方法介绍(代码示例)
    Laravel 事务中使用悲观锁
    array_reduce — 用回调函数迭代地将数组简化为单一的值
    PHP上传文件和下载
    php导出xls,报错:文件格式和扩展名不匹配。该文件可能已损坏或不安全。除非你相信它的来源,否则不要打开它。
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4441931.html
Copyright © 2011-2022 走看看