1. 程式人生 > >【20180311】2018北京集訓測試賽(二)

【20180311】2018北京集訓測試賽(二)

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北京集訓測試賽(二)