[P3613]睡觉困难综合征

Description:

给定一个n个点的树,每个点有一个操作符号 "&" "|" "^" ,以及一个权值

要求支持以下操作:

1.修改x点的操作符号和权值

2.给定w,你需要找一个数v,经过从x到y的路径上的所有运算后使答案最大,输出这个答案

Hint:

\(n \le 10^5\)

Solution:

这题是 https://www.cnblogs.com/list1/p/10499412.html 的树上多组询问带修版

原题需要维护每个位最初是0/1经运算后得到的是0还是1

所以我们这题也这么做

考虑如何在线段树上合并信息

\(f_{l0} ,f_{r0} ​\) 表示以0进入该节点区间,经运算后得到的值

分类讨论:

\(f_{l0}==1 \&\& f_{r1}==0​\)\(f_{l1}==0 \&\& f_{r0}==0​\)

\(f_{p0}=0​\)

同理我们可以推出其他四种转移,详见代码

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef unsigned long long ll;
const int mxn=2e5+5;
const ll lim=-1;
int n,q,k,t1,t2,cnt,tot;
int o[mxn],f[mxn],sz[mxn],hd[mxn],rk[mxn],top[mxn],dep[mxn],dfn[mxn],son[mxn];
ll a[mxn];

inline ll read() {
    char c=getchar(); ll x=0,f=1;
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    return x*f;
}
inline int chkmax(int &x,int y) {if(x<y) x=y;}
inline int chkmin(int &x,int y) {if(x>y) x=y;}

struct data {
    ll f0,f1,inv0,inv1;
    data() {f0=f1=inv0=inv1=0;}
}tr[mxn<<2],r1[mxn],r2[mxn];

struct ed {
    int to,nxt;
}t[mxn<<1];

inline void add(int u,int v) {
    t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void dfs1(int u,int fa) 
{
    dep[u]=dep[fa]+1; sz[u]=1; f[u]=fa;
    for(int i=hd[u];i;i=t[i].nxt) {
        int v=t[i].to;
        if(v==fa) continue ;
        dfs1(v,u); sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v;
    }
}

void dfs2(int u,int tp) 
{
    dfn[u]=++tot; rk[tot]=u; top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    for(int i=hd[u];i;i=t[i].nxt) {
        int v=t[i].to;
        if(v==f[u]||v==son[u]) continue ;
        dfs2(v,v);
    }
}

ll cal(ll val,int x)
{
    if(o[x]==1) return val&a[x];
    if(o[x]==2) return val|a[x];
    if(o[x]==3) return val^a[x];
}

data push_up(data lc,data rc) 
{
    data res;
    res.f0=((lc.f0&rc.f1)|((~lc.f0)&rc.f0));
    res.f1=((lc.f1&rc.f1)|((~lc.f1)&rc.f0));
    res.inv0=((rc.inv0&lc.inv1)|((~rc.inv0)&lc.inv0));
    res.inv1=((rc.inv1&lc.inv1)|((~rc.inv1)&lc.inv0));
    return res;
}

void build(int l,int r,int p) 
{
    if(l==r) {
        tr[p].f0=tr[p].inv0=cal(0,rk[l]);
        tr[p].f1=tr[p].inv1=cal(lim,rk[l]);
        return ;
    }
    int mid=(l+r)>>1; 
    build(l,mid,ls); 
    build(mid+1,r,rs);
    tr[p]=push_up(tr[ls],tr[rs]);
}

void update(int l,int r,int pos,int p)
{
    if(l==r) {
        tr[p].f0=tr[p].inv0=cal(0,rk[l]);
        tr[p].f1=tr[p].inv1=cal(lim,rk[l]);
        return ;
    }
    int mid=(l+r)>>1; 
    if(pos<=mid) update(l,mid,pos,ls);
    else update(mid+1,r,pos,rs);
    tr[p]=push_up(tr[ls],tr[rs]);
}

data query(int l,int r,int ql,int qr,int p)
{
    if(ql<=l&&r<=qr) return tr[p]; int mid=(l+r)>>1;
    if(qr<=mid) return query(l,mid,ql,qr,ls);
    else if(ql>mid) return query(mid+1,r,ql,qr,rs);
    else return push_up(query(l,mid,ql,qr,ls),query(mid+1,r,ql,qr,rs));
}

data solve(int x,int y) 
{
    t1=t2=0;
    while(top[x]!=top[y]) {
        if(dep[top[x]]>=dep[top[y]]) {
            r1[++t1]=query(1,n,dfn[top[x]],dfn[x],1);
            x=f[top[x]];
        }
        else {
            r2[++t2]=query(1,n,dfn[top[y]],dfn[y],1);
            y=f[top[y]];
        }
    }
    if(dep[x]>dep[y]) r1[++t1]=query(1,n,dfn[y],dfn[x],1);
    else r2[++t2]=query(1,n,dfn[x],dfn[y],1);
    data res;
    for(int i=1;i<=t1;++i) 
        swap(r1[i].f0,r1[i].inv0),swap(r1[i].f1,r1[i].inv1);
    if(t1) {
        res=r1[1];
        for(int i=2;i<=t1;++i) res=push_up(res,r1[i]);
        if(t2) res=push_up(res,r2[t2]);
    }	
    else res=r2[t2];
    for(int i=t2-1;i>=1;--i) res=push_up(res,r2[i]);
    return res;
}

int main()
{
    n=read(); q=read(); k=read(); int opt,u,v; ll w,ans;
    for(int i=1;i<=n;++i) o[i]=read(),a[i]=read();
    for(int i=1;i<n;++i) {
        u=read(); v=read();
        add(u,v); add(v,u);
    }
    dfs1(1,0); dfs2(1,1); build(1,n,1);
    for(int i=1;i<=q;++i) {
        opt=read(); u=read(); v=read(); w=read();
        if(opt==2) {
            o[u]=v; a[u]=w;
            update(1,n,dfn[u],1);
        }
        else {
            data res=solve(u,v); ans=0; ll tp0,tp1;
            for(int i=63;i>=0;--i) 
                if(res.f0>>i&1ull) ans|=1ull<<i;
                else if((res.f1>>i&1)&&(1ull<<i)<=w) ans|=1ull<<i,w-=1ull<<i;
            printf("%llu\n",ans);	
        }
    }
    return 0;
}

posted @ 2019-03-09 08:31  cloud_9  阅读(195)  评论(0编辑  收藏  举报