题意:起床困难综合征出到树上,带单点修改和区间询问
很容易想到在线段树上维护每一位遍历所有操作后会变成什么,但是第一次交TLE了。。。
然后发现我以前写了假的《又是nand》。。。我说怎么跑得这么慢。。。
维护上面说的这个东西并不需要64*2个bool变量,而是可以压到两个unsigned long long里,分别代表每一位输入为0和每一位输入为1。
将两个合并:若输入为0,经过左变量后某些bit会变成1,这些bit在输出中与”若输入为1”的右变量那些bit保持一致,其余bit与”若输入为0”的右变量那些bit保持一致,可得:
c.x0=(a.x0&b.x1)|(~a.x0&b.x0)
另一个同理。c.x1=(a.x1&b.x1)|(~a.x1&b.x0)
于是树剖就可以维护了。得到信息后从高位到低位贪心能选就选。
代码:
#include<cstdio>
#include<cstring>
#define gm 100001
using namespace std;
typedef unsigned long long ll;
int n,m,k;
struct Istream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Istream():buf(),s(),t(){}
char get()
{
return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++);
}
Istream& operator >> (int &x)
{
register char c;
do c=get(); while(c<'0'||c>'9');
x=0;
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
return *this;
}
Istream& operator>> (ll &x)
{
register char c;
do c=get(); while(c<'0'||c>'9');
x=0;
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
return *this;
}
}cin;
struct Ostream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Ostream():buf(),s(buf),t(buf+str){}
~Ostream(){fwrite(buf,1,s-buf,stdout);}
void put(char c)
{
(s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c);
}
Ostream& operator<< (ll x)
{
if(!x)
{
return put('0'),*this;
}
char a[22],t=1;
while(x)
a[t++]=x%10,x/=10;
while(--t)
put(a[t]+'0');
return *this;
}
Ostream& operator<< (const char *x)
{
while(*x) put(*x++);
return *this;
}
}cout;
const char *endl="\n";
struct info
{
ll a,b;
info(){}
info(const ll &x,int opt)
{
switch(opt)
{
case 1:
a=0,b=x;
break;
case 2:
a=x,b=~0ull;
break;
default:
a=x,b=~x;
}
}
info(const ll &a,const ll &b):a(a),b(b){}
bool operator () (int x,int y)
{
return y?(b>>x&1ull):(a>>x&1ull);
}
info operator + (const info &v) const
{
return info((a&v.b)|(~a&v.a),(b&v.b)|(~b&v.a));
}
}pre[262144],suf[262144],nil;
int op[gm];
ll val[gm];
ll pool[gm<<1],*ptr=pool;
struct e
{
int t;
e *n;
e(int t,e *n):t(t),n(n){}
inline void* operator new(size_t){return ++ptr;}
}*f[gm];
int sz[gm],fa[gm],son[gm],dfn[gm],dep[gm],top[gm],ord[gm],ct=0;
void dfs1(int x=1)
{
sz[x]=1;
for(e *i=f[x];i;i=i->n)
{
if(i->t==fa[x]) continue;
fa[i->t]=x;
dep[i->t]=dep[x]+1;
dfs1(i->t);
sz[x]+=sz[i->t];
if(sz[i->t]>=sz[son[x]]) son[x]=i->t;
}
}
void dfs2(int x=1)
{
ord[dfn[x]=++ct]=x;
top[x]=(x==son[fa[x]]?top[fa[x]]:x);
if(son[x]) dfs2(son[x]);
for(e *i=f[x];i;i=i->n)
{
if(i->t==fa[x]||i->t==son[x]) continue;
dfs2(i->t);
}
}
void build(int l=1,int r=n,int o=1)
{
if(l==r)
{
pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]);
return;
}
int mid=l+r>>1,ls=o<<1,rs=ls|1;
build(l,mid,ls);
build(mid+1,r,rs);
pre[o]=pre[ls]+pre[rs];
suf[o]=suf[rs]+suf[ls];
}
int x,y;
void cast(int l=1,int r=n,int o=1)
{
if(l==r)
{
pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]);
return;
}
int mid=l+r>>1,ls=o<<1,rs=ls|1;
if(x<=mid) cast(l,mid,ls);
else cast(mid+1,r,rs);
pre[o]=pre[ls]+pre[rs];
suf[o]=suf[rs]+suf[ls];
}
info getpr(int l=1,int r=n,int o=1)
{
if(x<=l&&r<=y)
{
return pre[o];
}
int mid=l+r>>1,ls=o<<1,rs=ls|1;
if(y<=mid) return getpr(l,mid,ls);
if(mid<x) return getpr(mid+1,r,rs);
return getpr(l,mid,ls)+getpr(mid+1,r,rs);
}
info getsf(int l=1,int r=n,int o=1)
{
if(x<=l&&r<=y)
{
return suf[o];
}
int mid=l+r>>1,ls=o<<1,rs=ls|1;
if(y<=mid) return getsf(l,mid,ls);
if(mid<x) return getsf(mid+1,r,rs);
return getsf(mid+1,r,rs)+getsf(l,mid,ls);
}
int LCA(int a,int b)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) a^=b^=a^=b;
a=fa[top[a]];
}
return dep[a]<dep[b]?a:b;
}
info query(int a,int b)
{
int lca=LCA(a,b);
info ra=nil,rb=nil,res;
while(top[a]!=top[lca])
{
x=dfn[top[a]],y=dfn[a];
ra=ra+getsf();
a=fa[top[a]];
}
x=dfn[lca],y=dfn[a];
ra=ra+getsf();
while(top[b]!=top[lca])
{
x=dfn[top[b]],y=dfn[b];
rb=getpr()+rb;
b=fa[top[b]];
}
if(b!=lca)
{
x=dfn[lca]+1,y=dfn[b];
rb=getpr()+rb;
}
return ra+rb;
}
int main()
{
cin>>n>>m>>k;
nil.a=0,nil.b=(k==64?~0ull:(1ull<<k)-1);
for(int i=1;i<=n;++i)
cin>>op[i]>>val[i];
for(int i=1;i<n;++i)
{
int u,v;
cin>>u>>v;
f[u]=new e(v,f[u]);
f[v]=new e(u,f[v]);
}
dfs1(),dfs2(),build();
for(int i=1;i<=m;++i)
{
int tp,x,y;
ll z;
cin>>tp>>x>>y>>z;
if(tp==1)
{
info res=query(x,y);
ll ans=0,kre=0;
for(int i=k-1;~i;--i)
{
if(res(i,0)) ans|=1ull<<i;
else if(res(i,1)&&(kre|(1ull<<i))<=z)
kre|=1ull<<i,ans|=1ull<<i;
}
cout<<ans<<endl;
}
else
{
op[x]=y,val[x]=z;
::x=dfn[x];
cast();
}
}
return 0;
}