题解 P5522 【[yLOI2019] 棠梨煎雪】

_虹_

2019-09-08 22:08:36

Solution

其实状压+线段树是很显然的。 主要难度在于合并区间信息。 三进制显然是不星的,O(nqlogm)比较危险(~~卡常神仙Orz~~),得想点办法在二进制下解决问题做到O(qlogm)。 具体解释写在代码里了。 | & ^这三个位运算居然不是同一个优先级。。。。。 ```cpp #include <iostream> #include <string> using namespace std; struct unit{ int bit=0;//1 表示1 0表示0或pending int pending=0; }; struct node{ unit res; int l,r; }; inline int ls(int i) { return i<<1; } inline int rs(int i) { return ls(i)|1; } const int kmaxn=1000000+10+5; const int failbit=1<<30; node T[kmaxn<<2]; string rd[kmaxn]; unit merge(const unit& l,const unit& r) { unit res; res.pending=l.pending & r.pending; int cfm=l.pending ^ r.pending;//获取只有一方pending的bit,称为cfm bit cfm=(l.bit | r.bit) & cfm;//对于一个cfm bit,因为l/r中有且只有一方确定了该位,而pending状态表示为0 //所以若l/r中有一方该位为1,则该位应为1(1&pending),否则为0(0&pending) res.bit=l.bit | cfm; if(res.bit ^ (r.bit | cfm))//双方将新确定的bit更新后不相同,说明有确定的bit不同,说明不存在复读机 res.bit|=failbit; //当然也可以xor取出双方不同的bit和cfm bit比较,若存在一个1在cfm中不存在而双方xor中存在,则不存在复读机 //这个方法貌似更好想一点 /* res.bit=l.bit | r.bit; int dif=l.bit ^ r.bit; if((dif|cfm) ^ cfm) res.bit|=failbit; */ return res; } void upd(int p) { if(T[p].l==T[p].r)return; T[p].res=merge(T[ls(p)].res,T[rs(p)].res); } unit init(int k) { unit res; for(int i=0;i<rd[k].size();++i) { switch(rd[k][i]) { case '0': case '1': res.bit+=(rd[k][i]-'0')<<i; break; case '?': res.pending+=1<<i; } } return res; } void build(int l,int r,int p=1) { T[p].l=l;T[p].r=r; if(l==r) { T[p].res=init(l); return; } int mid=(l+r)>>1; build(l,mid,ls(p)); build(mid+1,r,rs(p)); upd(p); } unit query(int l,int r,int p=1) { if(T[p].l==l&&r==T[p].r) return T[p].res; int mid=(T[p].l+T[p].r)>>1; if(r<=mid)return query(l,r,ls(p)); else if(l>mid)return query(l,r,rs(p)); else return merge(query(l,mid,ls(p)),query(mid+1,r,rs(p))); } void mod(int k,int p=1) { if(T[p].l==T[p].r) { T[p].res=init(k); return; } int mid=(T[p].l+T[p].r)>>1; if(k<=mid) mod(k,ls(p)); else mod(k,rs(p)); upd(p); } int n,q; int opt,x,y; int ans; unit u; inline int lowbit(int i) { return i&(-i); } int main() { ios::sync_with_stdio(false); cin>>n>>n>>q; for(int i=1;i<=n;++i) { cin>>rd[i]; } build(1,n); // cout<<1<<endl; while(q--) { cin>>opt>>x; if(opt) { cin>>rd[x]; mod(x); } else { cin>>y; u=query(x,y); if(u.bit&failbit) continue; x=1; // cout<<"pd "<<u.pending<<endl; while(u.pending) { x<<=1; u.pending-=lowbit(u.pending); } // cout<<x<<endl; ans^=x; } } cout<<ans<<endl; return 0; } ``` ------------ ~~什么神仙状压题~~