luogu P3613 睡觉困难综合征
2017-08-31 21:18
316 查看
题目地址
做法和原题差不多原题地址
显然每一个节点开一个大小为K的数组储存答案肯定是不行的
但是kk<=64,所以可以开一个unsignedlonglongunsignedlonglong储存答案
但是合并答案有点恶心
每个节点储存两个值AA和BB,AA表示INFINF经过操作后的值,BB表示00经过操作后的值
对于一个节点
首先LALA,LBLB为左边的答案,RARA,RBRB为右边的答案
以A为例
对于每一位i
如果LALA的第ii位为00那么A的第ii位的值为RARA的第ii位
如果LALA的第ii位为11那么A的第ii位的值为RBRB的第ii位
得A=((notLA)andRA)or(LAandRB)A=((notLA)andRA)or(LAandRB)
同理B=((notLB)andRA)or(LBandRB)B=((notLB)andRA)or(LBandRB)
那么这题就可以树链剖分或者LCT(大常数树)
个人比较推荐树链剖分,因为LCT不仅难调而且还不好写并且常数还巨大
因为LCT有翻转操作所以还要维护RevARevA和RevBRevB表示反向操作的答案
总之能不写LCT就不写
ps:但是我还是写的LCT
做法和原题差不多原题地址
显然每一个节点开一个大小为K的数组储存答案肯定是不行的
但是kk<=64,所以可以开一个unsignedlonglongunsignedlonglong储存答案
但是合并答案有点恶心
每个节点储存两个值AA和BB,AA表示INFINF经过操作后的值,BB表示00经过操作后的值
对于一个节点
首先LALA,LBLB为左边的答案,RARA,RBRB为右边的答案
以A为例
对于每一位i
如果LALA的第ii位为00那么A的第ii位的值为RARA的第ii位
如果LALA的第ii位为11那么A的第ii位的值为RBRB的第ii位
得A=((notLA)andRA)or(LAandRB)A=((notLA)andRA)or(LAandRB)
同理B=((notLB)andRA)or(LBandRB)B=((notLB)andRA)or(LBandRB)
那么这题就可以树链剖分或者LCT(大常数树)
个人比较推荐树链剖分,因为LCT不仅难调而且还不好写并且常数还巨大
因为LCT有翻转操作所以还要维护RevARevA和RevBRevB表示反向操作的答案
总之能不写LCT就不写
ps:但是我还是写的LCT
#include <cstdio> #include <cctype> #include <cmath> #include <algorithm> #define File(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout) using namespace std; namespace Data_stream{ const int IN_LEN=1<<17; const int OUT_LEN=1<<17; char buf[IN_LEN],obuf[OUT_LEN],*pcur=obuf,*HEAD=buf,*TAIL=buf,ch; int BUF,PS=0,Buf[30]; bool sign; inline char gec(){ if(HEAD==TAIL){ TAIL=(HEAD=buf)+fread(buf,1,IN_LEN,stdin); if(HEAD==TAIL)return EOF; } return *HEAD++; } inline void puc(char ch){ if(pcur==obuf+OUT_LEN){ fwrite(obuf,1,OUT_LEN,stdout); pcur=obuf; } *pcur++=ch; } template <typename T> inline int read(T&a){ for(sign=0,ch=gec();!isdigit(ch)&&ch!=EOF;ch=gec()) if(ch=='-')sign=1; if(ch==EOF)return EOF; for(a=0;isdigit(ch);ch=gec())a=((a+(a<<2))<<1)+(ch^'0'); if(sign)a=-a; return 0; } template <typename T> inline void print(T x){ if(x<0)puc('-'),x=-x; for(;x;x=BUF) BUF=x/10,Buf[++PS]=x-((BUF+(BUF<<2))<<1); while(PS)puc('0'^Buf[PS--]); } inline void flush(){ fwrite(obuf,1,pcur-obuf,stdout); } } using namespace Data_stream; #define Hf(x) (x->f?((x->f->s[0]==x)||(x->f->s[1]==x)):0) #define Get(type) (type=(~type&s[1]->Fz)|(type&s[1]->Fe)) #define Get_(type) (type=(~type&s[0]->Rfz)|(type&s[0]->Rfe)) typedef unsigned long long Ul; const int N=2e5+10; const Ul INF=0xffffffffffffffff;//Max unsigned long long inline void Calc(Ul&v,const Ul&val,const int&opt){(!opt)?(v&=val):((opt&1)?(v|=val):(v^=val));} struct Tree{ Tree(int opt=0,Ul v=0):opt(opt),v(v){Fz=Fe=Rfz=Rfe=0;rev=0;s[0]=s[1]=f=0;} int opt; Ul Fz,Fe,Rfz,Rfe,v; bool rev; Tree *s[2],*f; inline void Push(){ if(!rev)return; rev=0;swap(s[0],s[1]); swap(Fz,Rfz);swap(Fe,Rfe); if(s[0])s[0]->rev^=1; if(s[1])s[1]->rev^=1; } inline void Update(){ if(s[0])Fz=s[0]->Fz,Fe=s[0]->Fe; else Fz=0,Fe=INF; Calc(Fz,v,opt);Calc(Fe,v,opt); if(s[1])Get(Fz),Get(Fe),Rfz=s[1]->Rfz,Rfe=s[1]->Rfe; else Rfz=0,Rfe=INF; Calc(Rfz,v,opt);Calc(Rfe,v,opt); if(s[0])Get_(Rfz),Get_(Rfe); } void*operator new(size_t); }t ,*cur=t,*vec ,*stack ; inline void*Tree::operator new(size_t){return cur++;} int n,m,k,top; inline void Rot(Tree *p){ Tree *f=p->f;int v=(p!=f->s[0]); if(f->s[v]=p->s[v^1])f->s[v]->f=f; if(Hf(f))f->f->s[f!=f->f->s[0]]=p; p->f=f->f;p->s[v^1]=f;f->f=p; f->Update();p->Update(); } inline void Splay(Tree *p){ Tree *last; stack[++top]=p->s[0];stack[++top]=p->s[1]; for(last=p;Hf(p);p=p->f)stack[++top]=p->f->s[p==p->f->s[0]],stack[++top]=p; stack[++top]=p; for(;top;top--)if(stack[top])stack[top]->Push(); for(p=last;Hf(p);Rot(p)){ Tree *f=p->f; if(Hf(f)) Rot(((p!=f->s[0])^(f!=f->f->s[0]))?p:f); } } inline void Access(Tree *x){for(Tree *last=0;x;last=x,x=x->f){Splay(x);x->s[1]=last;x->Update();}} inline void MakeRoot(Tree *x){Access(x);Splay(x);x->rev^=1;} inline void link(Tree*x,Tree*y){MakeRoot(x);x->f=y;} inline void cut(Tree*x,Tree*y){MakeRoot(x);Access(y);Splay(x);x->s[1]=y->f=0;x->Update();} int main() { int x,y,type; Ul z; read(n);read(m);read(k); for(int i=1;i<=n;i++)read(t[i].opt),t[i].opt--,read(t[i].v),t[i].Update(); for(int i=1;i<n;i++)read(x),read(y),link(t+x,t+y); while(m--){ read(type);read(x);read(y);read(z); if(type&1){ MakeRoot(t+x);Access(t+y);Splay(t+y); Ul Fz=t[y].Fz,Fe=t[y].Fe,Ans=0; for(int i=k-1;~i;i--){ Ul P=(Ul)1<<i; if((Fe&P)&&!(Fz&P)&&(z>=P))Ans|=P,z-=P; else Ans|=Fz&P; } printf("%llu\n",Ans); } else{ Splay(t+x);t[x].opt=y-1;t[x].v=z; t[x].Update(); } } return 0; }
相关文章推荐
- 洛谷P3613 睡觉困难综合征
- 【树链剖分】LGP3613 睡觉困难综合征
- Luogu3613 睡觉困难综合征
- Luogu3613 睡觉困难综合征
- luogu3613 睡觉困难综合征(lct+贪心)
- luogu3613 睡觉困难综合征
- [洛谷]P3613 睡觉困难综合征
- Luogu 睡觉困难综合征 ([NOI2014]起床困难综合症)
- 省队集训Day1 睡觉困难综合征
- 洛谷P3613 睡觉困难综合征
- 洛谷P3613:睡觉困难综合征 (LCT+二进制压位)
- 2017.10.19 起床困难综合征 思考记录
- 洛谷3613:睡觉困难综合症(LCT+机巧的位运算)
- [BZOJ3668]NOI2014起床困难综合征|贪心
- [UOJ#2] [NOI2014] 起床困难综合征
- [bzoj3668][Noi2014]起床困难综合症/[洛谷3613]睡觉困难综合症
- [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]
- 【NOI 2014】起床困难综合征 拆位+贪心
- [日记] 晕呐,上班时间睡觉了!
- 遇到困难:PB如何调用由C#创建组件的功能?