码迷,mamicode.com
首页 > 其他好文 > 详细

【20180311】2018北京集训测试赛(二)

时间:2018-03-11 20:57:05      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:北京   iostream   直接   std   技术   alt   范围   现在   uil   

Problem A: 游戏

技术分享图片
技术分享图片

题解&反思

模型转化挺简单的,但是转化成“查询区间内是否有若干个数组成的集合xor和为0”问题的时候,突然发现不会做……最后只打了20暴力真是凉凉。
其实线性基这个东西我应该见过好多次,然而每次都因为某些奇怪的原因没有学……今天终于填了这个坑啊。
参考:https://www.cnblogs.com/ljh2000-jump/p/5869991.html
这道题就是用线段树维护线性基。首先,ai的的范围是2^30,所以当查询区间大于30时,线性基一定小于区间数的个数,也就是一定能凑出来0,直接回答即可;否则,枚举l到r,插进线性基里,如果某次插入失败则说明能凑出0,否则puts("No");
至于线段树上的标记维护比较神奇,我已开始想的是维护&|^三个标记,结果不会写,可以维护两个标价mn和mx,互为二进制反数……好吧我现在也不知道这是维护了个啥,总之先背下来就好了= =

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500005,sz=32768,inf=(1<<30)-1;
int n,q,a[N],b[N],v[35];
struct qwe
{
    int l,r,mn,mx;
}t[N<<2];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=-1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
int hig(int x)
{
    return x>sz?b[x>>15]+15:b[x];
}
inline void hb(qwe &now,qwe x)
{
    int p=now.mn,q=now.mx;
    now.mn=(p&x.mx)|((inf^p)&x.mn);
    now.mx=(q&x.mx)|((inf^q)&x.mn);
}
inline void pd(int k)
{
    hb(t[k<<1],t[k]);
    hb(t[k<<1|1],t[k]);
    t[k].mn=0,t[k].mx=inf;
}
void build(int ro,int l,int r)
{
    t[ro].l=l,t[ro].r=r;
    t[ro].mx=inf;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build(ro<<1,l,mid);
    build(ro<<1|1,mid+1,r);
}
void update(int ro,int l,int r,int o,int x)
{
    if(t[ro].l==l&&t[ro].r==r)
    {
        if(o==1)
            t[ro].mn&=x,t[ro].mx&=x;
        else if(o==2)
            t[ro].mn|=x,t[ro].mx|=x;
        else if(o==3)
            t[ro].mn^=x,t[ro].mx^=x;
        return;
    }
    pd(ro);
    int mid=(t[ro].l+t[ro].r)>>1;
    if(r<=mid)
        update(ro<<1,l,r,o,x);
    else if(l>mid)
        update(ro<<1|1,l,r,o,x);
    else
    {
        update(ro<<1,l,mid,o,x);
        update(ro<<1|1,mid+1,r,o,x);
    }
}
qwe ques(int ro,int w)
{
    if(t[ro].l==t[ro].r)
        return t[ro];
    pd(ro);
    int mid=(t[ro].l+t[ro].r)>>1;
    if(w<=mid)
        return ques(ro<<1,w);
    else
        return ques(ro<<1|1,w);
}
int wen(int p)
{
    qwe now=ques(1,p);
    int q=a[p];
    return (q&now.mx)|((inf^q)&now.mn);
}
bool add(int x)
{
    int i;
    for(i=hig(x);i>=0;i=hig(x))
    {
        if(v[i]==0)
        {
            v[i]=x;
            break;
        }
        x^=v[i];
    }
    return i>=0;
}
int main()
{
    b[0]=-1;
    for(int i=1;i<=sz;i++)
        b[i]=b[i>>1]+1;
    n=read();
    build(1,1,n);
    for(int i=1;i<=n;i++)
        a[i]=read();
    q=read();
    while(q--)
    {
        int o=read(),l=read(),r=read();
        if(o)
        {
            int x=read();
            update(1,l,r,o,x);
        }
        else
        {
            if(r-l+1>30)
            {
                puts("Yes");
                continue;
            }
            bool f=1;
            memset(v,0,sizeof(v));
            for(int j=l;j<=r;j++)
                if(!add(wen(j))) 
                {
                    f=0;
                    break;
                }
            if(f)
                puts("No");
            else
                puts("Yes");
        }
    }
    return 0;
}

【20180311】2018北京集训测试赛(二)

标签:北京   iostream   直接   std   技术   alt   范围   现在   uil   

原文地址:https://www.cnblogs.com/lokiii/p/8545442.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!