• 【或位运算】【构造】


    题面

    算法

    关于这种有关二进制位的运算
    我们照例是对每一位进行考虑
    我们先把要构造的数列 (a_1,a_2,a_3······a_n)的二进制下的每一位初始值设为1
    然后对于一条指令 l,r,p 如果二进制下p的第x位为0 则把l~r的数这一位都设为0 这一步可以用差分来(O(n))实现
    我们已经对于每一条指令的0更新完毕
    接下来考虑如果二进制下p的第x位为1,则l~r的数这一位的和不为0,如果不满足则证明无解
    然后按照我们给的二进制下每个数的每一位还原原数组即可

    代码

    #include<iostream>
    #include<cstdio>
    #define M 100050
    #define ll long long
    using namespace std;
    ll biao[40][M],num[M];//第一维:二进制第几位 第二维:第几个数
    ll n,m,s[40][M];//s:前缀和 判断1的时候用 
    struct QWQ{
    	ll l,r,p;
    }QAQ[M];//条件 
    void change(ll num)
    {
         for(ll i = 0;i <= 30;i++)
         if((QAQ[num].p&(1 << i)) == 0)
    	 biao[i][QAQ[num].l] --,biao[i][QAQ[num].r + 1] ++;
    	 return ;    
    }
    bool  check(ll num)
    {
    	for(ll i = 0;i <= 30;i++)
    	{
    		if(QAQ[num].p&(1 << i))
    		if(s[i][QAQ[num].r] - s[i][QAQ[num].l - 1] == 0)
    		return 1;
    	}
    	return 0;
    }
    int main()
    {
    	freopen("or.in","r",stdin);
    	freopen("or.out","w",stdout);
    	scanf("%lld%lld",&n,&m);
    	for(ll i = 1;i <= m;i++)
        {
        	scanf("%lld%lld%lld",&QAQ[i].l,&QAQ[i].r,&QAQ[i].p);
    	    change(i); 
    	} 
    	for(ll i = 0;i <= 30;i++)
    	for(ll j = 1;j <= n;j++)
    	{
    		biao[i][j] += biao[i][j - 1];
    		if(biao[i][j] >= 0)
    		num[j] |= (1 << i),s[i][j] = 1;
    		s[i][j] += s[i][j - 1];
    	} 
    	for(ll i = 1;i <= m;i++)
        if(check(i))
    	{
    		cout<<"No"<<endl;
    		return 0;
    	}	
    	cout<<"Yes"<<endl;
    	for(ll i = 1;i <= n;i++)
    	cout<<num[i]<<" ";
            return 0;
    }
    
  • 相关阅读:
    vim配置文件
    NGUI屏幕自适应解决方案
    配置java环境
    Ignore files which are already versioned
    Unity3D TestTool Part _1
    c# 语法
    Application.persistentDataPath 的一个小坑
    Unity3D Log 收集机制
    Android 问题流水总结
    Open Phone, SMS, Email, Skype and Browser apps of Android in Unity3d
  • 原文地址:https://www.cnblogs.com/dixiao/p/13714605.html
Copyright © 2020-2023  润新知