• CF1148F Foo Fighters(构造,贪心)


    洛谷传送门


    解题思路

    按mask二进制位,把物品分类。
    设sum[i]为mask共有i位的物品的val的和。
    因为若答案的第i位为1,对mask小于i位的物品是没有影响的。
    于是我们从低位向高位枚举,这样就保证了后面的决策不会影响前面已经决定了的状态。
    因为只要求答案变成相反数,所以只要每一个sum[i]变成与总的sum异号即可。
    同时,在更改当前位时,需要把当前位为1的每一个物品的val变成相反数并更新后面的sum。
    感觉这不是一个真正意义上的贪心,其并不满足最优子结构的要求。
    因为这样只能求出一组解,而不是最优解。

    注意:用 1<<i 时,一定要写成 1ll<<i。
    一天一个好习惯,noip不爆零。

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=3e5+5;
    int n,ans[65];
    long long anss,sum[maxn],tot;
    struct node{
    	long long val,mask;
    }a[maxn];
    vector<int> b[maxn];
    inline void update(int i,int p){
    	int cnt=0;
    	long long x=a[i].mask;
    	if(x&(1ll<<(p-1))){
    		while(x>0){
    			x/=2;
    			cnt++;
    		}
    		sum[cnt]-=2*a[i].val;
    		a[i].val=-a[i].val;
    	}
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>a[i].val>>a[i].mask;
    		tot+=a[i].val;
    		long long t=a[i].mask,cnt=0;
    		while(t>0){
    			t/=2;
    			cnt++;
    		}
    		b[cnt].push_back(i);
    		sum[cnt]+=a[i].val;
    	}
    	for(int i=1;i<=63;i++){
    		if((sum[i]!=0)&&(((sum[i]>0)^(tot>0))==0)){
    			ans[i]=1;
    			for(int j=1;j<=n;j++){
    				update(j,i);
    			}
    		}
    	}
    	for(int i=63;i>=1;i--){
    		anss=anss*2+ans[i];
    	}
    	cout<<anss;
        return 0;
    }
    
  • 相关阅读:
    python奇技淫巧——max/min函数的用法
    mysql中InnoDB存储引擎的行锁和表锁
    supervisor进程管理工具
    Tornado源码分析 --- Cookie和XSRF机制
    Tornado源码分析 --- Redirect重定向
    Tornado源码分析 --- 静态文件处理模块
    Tornado源码分析 --- Etag实现
    Python环境管理--virtualenvwrapper
    记录
    由 '' in 'abc' return True 引发的思考----Python 成员测试操作
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15322635.html
Copyright © 2020-2023  润新知