zoukankan      html  css  js  c++  java
  • [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
    ",ans);	
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    将您的基于 Accelerator 的 SAP Commerce Cloud Storefront 迁移到 Spartacus Storefront
    SAP S/4HANA: 一条代码线,许多种选择
    windows系统中远程登录ubuntu18服务器的桌面
    C语言格式控制符/占位符
    C语言变量声明和定义
    C语言数据类型 / 变量类型
    C语言 Hello World
    C语言代码注释
    变量命名 – 匈利亚命名法则
    设置 Visual Studio 字体/背景/行号
  • 原文地址:https://www.cnblogs.com/list1/p/10499402.html
Copyright © 2011-2022 走看看