# BZOJ4811: [Ynoi2017]由乃的OJ

BZOJ4811: [Ynoi2017]由乃的OJ

## Description

Deus：这个题怎么做呀？
yuno：这个不是NOI2014的水题吗。。。
Deus：那如果出到树上，多组链询问，带修改呢？
yuno：诶。。。？？？
Deus：这题叫做睡觉困难综合征哟~

## Input

0 <= n , m <= 100000 , k <= 64

5 5 3
1 7
2 6
3 7
3 6
3 1
1 2
2 3
3 4
1 5
1 1 4 7
1 1 3 5
2 1 1 3
2 3 3 3
1 1 3 2

7
1
5

# BZOJ3668: [Noi2014]起床困难综合症

$0$从前到后取一遍的值，$(1111111...1)_2$从前到后取一遍的值；

$0$从后向前取一遍的值，$(1111111...1)_2$从后向前取一遍的值。

$$f_0[u][i]=(f_0[l][i]\&f_1[r][i])|(!f_0[l][i]\&f_0[r][i])$$

$$f_0[u]=((f_0[l]\&f_1[r])|((!f_0[l])\&f_1[r]))$$

$$f_1[u]=((f_1[l]\&f_1[r])|((\!f_1[l])\&f_0[r]))$$

$u->LCA(u,v),LCA(u,v)->v$

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATAL(x) a[x].data0
#define DATAR(x) a[x].data1
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define MAXN 100010
using namespace std;
const unsigned long long MIN=0,MAX=~MIN;
int n,m,q,c=1,d=1,top1,top2;
struct Tree{
int next,to;
}tree[MAXN<<1];
struct data{
unsigned long long v,w;
friend data operator +(const data &p,const data &q){
data now;
now.v=(p.v&q.w)|((~p.v)&q.v);
now.w=(p.w&q.w)|((~p.w)&q.v);
return now;
}
}val[MAXN];
struct Segment_Tree{
data data0,data1;
int l,r;
friend Segment_Tree operator +(const Segment_Tree &p,const Segment_Tree &q){
Segment_Tree now;
now.data0=p.data0+q.data0;now.data1=q.data1+p.data1;
now.l=p.l;now.r=q.r;
return now;
}
}a[MAXN<<2],ans1[MAXN],ans2[MAXN];
long long date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline data calculate(int operate,unsigned long long x){
switch(operate){
case 1:return (data){MIN&x,MAX&x};
case 2:return (data){MIN|x,MAX|x};
case 3:return (data){MIN^x,MAX^x};
}
}
}
void dfs1(int rt){
son[rt]=0;size[rt]=1;
will=tree[i].to;
if(!deep[will]){
deep[will]=deep[rt]+1;
fa[will]=rt;
dfs1(will);
size[rt]+=size[will];
if(size[son[rt]]<size[will])son[rt]=will;
}
}
}
void dfs2(int rt,int f){
id[rt]=d++;pos[id[rt]]=rt;top[rt]=f;
if(son[rt])dfs2(son[rt],f);
will=tree[i].to;
if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);
}
}
inline void pushup(int rt){
DATAL(rt)=DATAL(LSON)+DATAL(RSON);
DATAR(rt)=DATAR(RSON)+DATAR(LSON);
}
void buildtree(int l,int r,int rt){
LSIDE(rt)=l;RSIDE(rt)=r;
if(l==r){
DATAL(rt)=DATAR(rt)=val[pos[l]];
return;
}
int mid=l+r>>1;
buildtree(l,mid,LSON);
buildtree(mid+1,r,RSON);
pushup(rt);
}
void update(int k,data c,int rt){
if(LSIDE(rt)==RSIDE(rt)){
DATAL(rt)=DATAR(rt)=c;
return;
}
int mid=LSIDE(rt)+RSIDE(rt)>>1;
if(k<=mid)update(k,c,LSON);
else update(k,c,RSON);
pushup(rt);
}
Segment_Tree query(int l,int r,int rt){
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return a[rt];
int mid=LSIDE(rt)+RSIDE(rt)>>1;
if(r<=mid)return query(l,r,LSON);
else if(mid<l)return query(l,r,RSON);
else return (query(l,mid,LSON)+query(mid+1,r,RSON));
}
Segment_Tree query_path(int x,int y){
Segment_Tree ans;
top1=top2=0;
while(top[x]!=top[y]){
if(deep[top[x]]>=deep[top[y]]){
ans1[++top1]=query(id[top[x]],id[x],1);
x=fa[top[x]];
}
else{
ans2[++top2]=query(id[top[y]],id[y],1);
y=fa[top[y]];
}
}
if(deep[x]>deep[y])ans1[++top1]=query(id[y],id[x],1);
else ans2[++top2]=query(id[x],id[y],1);
for(int i=1;i<=top1;i++)swap(ans1[i].data0,ans1[i].data1);
if(top1){
ans=ans1[1];
for(int i=2;i<=top1;i++)ans=ans+ans1[i];
if(top2)ans=ans+ans2[top2];
}
else ans=ans2[top2];
for(int i=top2-1;i>=1;i--)ans=ans+ans2[i];
return ans;
}
void solve(int x,int y,unsigned long long z){
unsigned long long ans=0;
data t;
Segment_Tree s=query_path(x,y);
for(int i=63;i>=0;i--){
t.v=(s.data0.v>>i)&1uLL;
t.w=(s.data0.w>>i)&1uLL;
if(t.v>=t.w||(1uLL<<i)>z)ans|=(t.v?(1uLL<<i):0);
else{
ans|=(t.w?(1uLL<<i):0);
z-=(1ull<<i);
}
}
printf("%llu\n",ans);
}
void work(){
int f;
unsigned long long x,y,z;
while(m--){
if(f==1){
solve(x,y,z);
}
else{
update(id[x],calculate(y,z),1);
}
}
}
void init(){
int x,y;
unsigned long long k;
for(int i=1;i<=n;i++){
val[i]=calculate(x,k);
}
for(int i=1;i<n;i++){
}
deep[1]=1;
dfs1(1);
dfs2(1,1);
buildtree(1,n,1);
}
int main(){
init();
work();
return 0;
}
/*

Result: Accepted

Time: 3516 ms

Because of: Xuan_Xue......

*/


### $LCT$大法：

$$h_0=(\!f_0\&g_0)|(f_0\&g_1)$$
$$h_1=(\!f_1\&g_0)|(f_1\&g_1)$$

# 洛谷P3613 睡觉困难综合征

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 100010
using namespace std;
unsigned long long MIN=0,MAX=~MIN;
int n,m,q,c=1;
struct node1{
unsigned long long v,w;
}val[MAXN];
struct node2{
int f,flag,son[2];
node1 l,r;
}a[MAXN];
long long date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline long long operation(long long x,long long y,int opt){
if(!opt)return x;
switch(opt){
case 1:{x&=y;break;}
case 2:{x|=y;break;}
case 3:{x^=y;break;}
}
return x;
}
inline node1 update(node1 x,node1 y){
node1 rt;
rt.v=(~x.v&y.v)|(x.v&y.w);
rt.w=(~x.w&y.v)|(x.w&y.w);
return rt;
}
inline bool isroot(int rt){
return a[a[rt].f].son[0]!=rt&&a[a[rt].f].son[1]!=rt;
}
inline void pushup(int rt){
if(!rt)return;
a[rt].l=a[rt].r=val[rt];
if(a[rt].son[0]){a[rt].l=update(a[a[rt].son[0]].l,a[rt].l);a[rt].r=update(a[rt].r,a[a[rt].son[0]].r);}
if(a[rt].son[1]){a[rt].l=update(a[rt].l,a[a[rt].son[1]].l);a[rt].r=update(a[a[rt].son[1]].r,a[rt].r);}
}
inline void reserve(int rt){
swap(a[rt].l,a[rt].r);swap(a[rt].son[0],a[rt].son[1]);
a[rt].flag^=1;
}
inline void pushdown(int rt){
if(!rt||!a[rt].flag)return;
reserve(a[rt].son[0]);reserve(a[rt].son[1]);
a[rt].flag^=1;
}
inline void turn(int rt){
int x=a[rt].f,y=a[x].f,k=a[x].son[0]==rt?1:0;
if(!isroot(x)){
if(a[y].son[0]==x)a[y].son[0]=rt;
else a[y].son[1]=rt;
}
a[rt].f=y;a[x].f=rt;a[a[rt].son[k]].f=x;
a[x].son[k^1]=a[rt].son[k];a[rt].son[k]=x;
pushup(x);pushup(rt);
}
void splay(int rt){
int top=0,stack[MAXN];
stack[++top]=rt;
for(int i=rt;!isroot(i);i=a[i].f)stack[++top]=a[i].f;
while(top)pushdown(stack[top--]);
while(!isroot(rt)){
int x=a[rt].f,y=a[x].f;
if(!isroot(x)){
if((a[y].son[0]==x)^(a[x].son[0]==rt))turn(rt);
else turn(x);
}
turn(rt);
}
}
void access(int rt){
for(int i=0;rt;i=rt,rt=a[rt].f){
splay(rt);
a[rt].son[1]=i;
pushup(rt);
}
}
inline void makeroot(int rt){access(rt);splay(rt);reserve(rt);}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void answer(unsigned long long sum0,unsigned long long sum1,unsigned long long maxn){
unsigned long long ans=0,t=1;
for(int i=63;i>=0;i--){
if(sum0&(t<<i))ans+=(t<<i);
else if(maxn>=(t<<i)&&(sum1&(t<<i))){
maxn-=(t<<i);
ans+=(t<<i);
}
}
printf("%llu\n",ans);
}
void work1(int x,int y,unsigned long long k){
split(x,y);
}
void work2(int x,int y,unsigned long long k){
switch(y){
case 1:val[x]=(node1){MIN,k};break;
case 2:val[x]=(node1){k,MAX};break;
case 3:val[x]=(node1){k,~k};break;
}
splay(x);
}
void work(){
int f,x,y;
unsigned long long k;
while(m--){
if(f==1)work1(x,y,k);
if(f==2)work2(x,y,k);
}
}
void init(){
int x,y;
unsigned long long k;
for(int i=1;i<=n;i++){
switch(x){
case 1:val[i]=(node1){MIN,k};break;
case 2:val[i]=(node1){k,MAX};break;
case 3:val[i]=(node1){k,~k};break;
}
}
for(int i=1;i<n;i++){
}
}
int main(){
init();
work();
return 0;
}
/*

Result: Time_Limit_Exceed

Because of: chang_shu.....

Solution: No_Solution......

*/


posted @ 2018-11-10 22:42 符拉迪沃斯托克 阅读(...) 评论(...) 编辑 收藏
Live2D