luogu 2114 [NOI2014]起床困难综合症 位运算+贪心

感觉这个思路非常巧妙啊~

code: 

#include <bits/stdc++.h>  
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
ll qpow[40];   
int main() 
{ 
    // setIO("input"); 
    ll a=0,b=0,re=0;    
    int i,j,n,m;    
    scanf("%d%d",&n,&m);           
    for(i=0;i<40;++i) qpow[i]=1ll<<i, a+=qpow[i];    
    for(i=1;i<=n;++i) 
    {         
        ll x; 
        char op[5];   
        scanf("%s%lld",op,&x); 
        if(op[0]=='A') a&=x,b&=x;   
        if(op[0]=='O') a|=x,b|=x;    
        if(op[0]=='X') a^=x,b^=x;    
    }   
    for(i=33;i>=0;--i) 
    {
        if(b&qpow[i]) re+=qpow[i];  
        else if(a&qpow[i] && qpow[i]<=1ll*m) re+=qpow[i], m-=(int)qpow[i];   
    }
    printf("%lld\n",re);  
    return 0; 
}

  

线段树版(可以改装改装加个单点修改之类的) 

code:

#include <bits/stdc++.h> 
#define N 100005     
#define lson now<<1 
#define rson now<<1|1   
#define ll unsigned long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;       
int n,m;  
struct node 
{  
    ll f0,f1;   
    node operator+(const node &b)const 
    {
        node a;      
        a.f0=(~f0&b.f0)|(f0&b.f1);            
        a.f1=(~f1&b.f0)|(f1&b.f1);     
        return a; 
    }   
}f[N<<2],A[N];    
void build(int l,int r,int now) 
{
    if(l==r) 
    {   
        f[now]=A[l];  
        return;   
    }
    int mid=(l+r)>>1;   
    if(l<=mid) build(l,mid,lson);
    if(r>mid)  build(mid+1,r,rson);        
    f[now]=f[lson];   
    if(rson) f[now]=f[now]+f[rson];          
}    
int main() 
{  
    // setIO("input");  
    int i,j; 
    scanf("%d%d",&n,&m);   
    for(i=1;i<=n;++i) 
    {  
        ll x; 
        char op[5];  
        scanf("%s%llu",op,&x);           
        if(op[0]=='A') A[i]=(node){0,x};    
        if(op[0]=='O') A[i]=(node){x,~0};     
        if(op[0]=='X') A[i]=(node){x,~x};    
    } 
    build(1,n,1);          
    ll re=0;    
    for(i=32;i>=0;--i) 
    {    
        if(f[1].f0&(1ll<<i)) re+=(1ll<<i);  
        else if((f[1].f1&(1ll<<i)) && (1ll<<i)<=1ll*m) 
        {
            m-=(int)(1ll<<i);     
            re+=(1ll<<i);    
        }
    }
    printf("%lld\n",(long long)re);    
    return 0; 
}

  

posted @ 2019-10-10 14:48  EM-LGH  阅读(168)  评论(0编辑  收藏  举报