您的位置:首页 > 其它

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

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: