Solution -「YunoOI 2017」由乃的 OJ
Description
Link.
起床困难综合症 上树。
Solution
线段树维护,树剖上树。
具体题解有空再写,我要去睡觉了。
#include<bits/stdc++.h>
typedef unsigned long long ULL;
struct node {
ULL one,zero;
node(ULL A=0,ULL B=0) {
one=A;
zero=B;
}
}nodes[400010],exnodes[400010],res,exres;
ULL poi[100010],opz;
int k,dep[100010],son[100010],hb[100010],fa[100010],dfn[100010],sjc,op[100010],n,m,rev[100010],siz[100010];
int head[100010],nxt[200010],to[200010],cntot,opt,opx,opy;
bool flag,exflag;
void addEdge(int one,int ano) {
to[++cntot]=ano;
nxt[cntot]=head[one];
head[one]=cntot;
}
node merge(node one,node ano) {
node res(~0ull);
ULL tmp=one.one,extmp=~tmp;
res.one=(tmp&ano.one)|(extmp&ano.zero);
tmp=one.zero;
extmp=~tmp;
res.zero=(tmp&ano.one)|(extmp&ano.zero);
return res;
}
void adj(ULL &x,ULL y,int id) {
if(id==1) {
x&=y;
} else if(id==2) {
x|=y;
} else {
x^=y;
}
}
void build(int l,int r,int x) {
if(l^r) {
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
nodes[x]=merge(nodes[x<<1],nodes[x<<1|1]);
exnodes[x]=merge(exnodes[x<<1|1],exnodes[x<<1]);
} else {
nodes[x]=exnodes[x]=node(~0ull);
adj(nodes[x].one,poi[rev[l]],op[rev[l]]);
adj(nodes[x].zero,poi[rev[l]],op[rev[l]]);
adj(exnodes[x].one,poi[rev[l]],op[rev[l]]);
adj(exnodes[x].zero,poi[rev[l]],op[rev[l]]);
}
}
void ins(int l,int r,int x,int pos,int aj,ULL val) {
if(l^r) {
int mid=(l+r)>>1;
if(mid>=pos) {
ins(l,mid,x<<1,pos,aj,val);
} else {
ins(mid+1,r,x<<1|1,pos,aj,val);
}
nodes[x]=merge(nodes[x<<1],nodes[x<<1|1]);
exnodes[x]=merge(exnodes[x<<1|1],exnodes[x<<1]);
} else {
op[rev[l]]=aj;
poi[rev[l]]=val;
nodes[x]=exnodes[x]=node(~0ull);
adj(nodes[x].one,poi[rev[l]],op[rev[l]]);
adj(nodes[x].zero,poi[rev[l]],op[rev[l]]);
adj(exnodes[x].one,poi[rev[l]],op[rev[l]]);
adj(exnodes[x].zero,poi[rev[l]],op[rev[l]]);
}
}
void find(int l,int r,int x,int fr,int ba) {
if(l>ba || r<fr) {
return;
} else {
if(l>=fr && r<=ba) {
if(!flag) {
res=nodes[x];
flag=true;
} else {
res=merge(nodes[x],res);
}
} else {
int mid=(l+r)>>1;
find(mid+1,r,x<<1|1,fr,ba);
find(l,mid,x<<1,fr,ba);
}
}
}
void exfind(int l,int r,int x,int fr,int ba) {
if(l>ba || r<fr) {
return;
} else {
if(l>=fr && r<=ba) {
if(!exflag) {
exres=exnodes[x];
exflag=true;
} else {
exres=merge(exres,exnodes[x]);
}
} else {
int mid=(l+r)>>1;
exfind(mid+1,r,x<<1|1,fr,ba);
exfind(l,mid,x<<1,fr,ba);
}
}
}
node LCA(int x,int y) {
flag=exflag=false;
res=exres=node(~0ull);
while(hb[x]^hb[y]) {
if(dep[hb[x]]>dep[hb[y]]) {
exfind(1,n,1,dfn[hb[x]],dfn[x]);
x=fa[hb[x]];
} else {
find(1,n,1,dfn[hb[y]],dfn[y]);
y=fa[hb[y]];
}
}
if(dep[x]<dep[y]) {
find(1,n,1,dfn[x],dfn[y]);
} else {
exfind(1,n,1,dfn[y],dfn[x]);
}
return merge(exres,res);
}
void dfs1(int x,int las) {
dep[x]=dep[las]+1;
fa[x]=las;
siz[x]=1;
for(int i=head[x];i;i=nxt[i]) {
int y=to[i];
if(y^las) {
dfs1(y,x);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]) {
son[x]=y;
}
}
}
}
void dfs2(int x,int t) {
hb[x]=t;
dfn[x]=++sjc;
rev[sjc]=x;
if(son[x]) {
dfs2(son[x],t);
for(int i=head[x];i;i=nxt[i]) {
int y=to[i];
if((y^fa[x]) && (y^son[x])) {
dfs2(y,y);
}
}
}
}
ULL solve(node now,ULL lim) {
ULL res=0,run=0;
for(int i=k-1;~i;--i) {
if(now.zero&(1ull<<i)) {
res+=(1ull<<i);
} else if((now.one&(1ull<<i)) && run+(1ull<<i)<=lim) {
run+=(1ull<<i);
res+=(1ull<<i);
}
}
return res;
}
char fgc() {
static char buf[1<<21],*p=buf,*q=buf;
return p==q && (q=buf+fread(p=buf,1,1<<21,stdin),p==q)?EOF:*p++;
}
template<typename T>
void read(T &hhh) {
T x=0;
int f=0;
char c=fgc();
while(c<'0' || c>'9') {
if(c=='-') {
f=1;
}
c=fgc();
}
while(c>='0' && c<='9') {
x=(x<<3)+(x<<1)+(c^'0');
c=fgc();
}
if(f) {
hhh=-x;
} else {
hhh=x;
}
}
int wrstk[100];
template<typename T>
void write(T x,char las='\n') {
int top=0,f=0;
if(x<0) {
x=-x;
f=1;
}
do {
wrstk[++top]=x%10;
x/=10;
} while(x);
if(f) {
putchar('-');
}
while(top) {
putchar(wrstk[top--]^'0');
}
putchar(las);
}
int main() {
read(n);
read(m);
read(k);
for(int i=1;i<=n;++i) {
read(op[i]);
read(poi[i]);
}
for(int i=1,x,y;i<n;++i) {
read(x);
read(y);
addEdge(x,y);
addEdge(y,x);
}
dfs1(1,0);
dfs2(1,1);
build(1,n,1);
while(m-->0) {
read(opt);
read(opx);
read(opy);
read(opz);
if(opt==1) {
if(k) {
write(solve(LCA(opx,opy),opz));
} else {
write(0);
}
} else {
ins(1,n,1,dfn[opx],opy,opz);
}
}
return 0;
}