【20180311】2018北京集訓測試賽(二)
阿新 • • 發佈:2018-03-11
char 開始 n) source 數組 區間 但是 多次 pan
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北京集訓測試賽(二)