萌新刚学树剖,求教睡觉困难综合征

P5354 [Ynoi2017] 由乃的 OJ

_WA自动机 @ 2019-05-09 16:22:03

30分感觉很失败啊...有没有人康康这份代码哪里错了啊/kel

#include <cstdio>
#include <cstring>
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <vector>
#define ls l,mid,o<<1
#define rs mid+1,r,o<<1|1

using std::vector;

const int maxn=1e5+1000;

vector<int> G[maxn];
int opr[maxn],opt[maxn];
int depth[maxn],fa[maxn],siz[maxn];
int top[maxn],son[maxn],id[maxn],cnt;
uint64_t f0[maxn<<2],f1[maxn<<2],g0[maxn<<2],g1[maxn<<2];
uint64_t val[maxn],w[maxn];

template<class T>inline void swap(T& a,T& b){a^=b^=a^=b;}

inline void dfs(int u,int ff,int dep)
{
    depth[u]=dep;
    fa[u]=ff;siz[u]=1;
    int maxs=-1;
    for (auto v:G[u])
    {
        if (v==ff) continue;
        dfs(v,u,dep+1);
        siz[u]+=siz[v];
        if (siz[v]>=maxs) maxs=siz[v],son[u]=v;
    }
}

inline void dfs(int u,int topf)
{
    id[u]=++cnt;
    val[cnt]=w[u];
    opt[cnt]=opr[u];
    top[u]=topf;
    if (!son[u]) return;
    dfs(son[u],topf);
    for (auto v:G[u]) 
        if (v!=fa[u] && v!=son[u]) dfs(v,v);
}

// 线段树 pushup操作
inline void pushup(int o)
{
    f0[o]=((~f0[o<<1])&f0[o<<1|1])|(f0[o<<1]&f1[o<<1|1]);
    f1[o]=((~f1[o<<1])&f0[o<<1|1])|(f1[o<<1]&f1[o<<1|1]);
    g0[o]=((~g0[o<<1|1])&g0[o<<1])|(g0[o<<1|1]&g1[o<<1]);
    g1[o]=((~g1[o<<1|1])&g0[o<<1])|(g1[o<<1|1]&g1[o<<1]);
}

inline uint64_t calc(uint64_t x,uint64_t y,int opt)
{
    if (opt==1) return x&y;
    if (opt==2) return x|y;
    if (opt==3) return x^y;
    // assert(0);
}

//线段树的建树
inline void build(int l,int r,int o)
{
    if (l==r)
    {
        g0[o]=f0[o]=calc(0,val[l],opt[l]);
        g1[o]=f1[o]=calc(UINT64_MAX,val[l],opt[l]);
        return;
    }
    int mid=(l+r)>>1;
    build(ls);build(rs);
    pushup(o);
}

// 线段树的单点更新
inline void update(int pos,uint64_t v,int opt,int l,int r,int o)
{
    if (l==r)
    {
        g0[o]=f0[o]=calc(0,v,opt);
        g1[o]=f1[o]=calc(UINT64_MAX,v,opt);
        return;
    }
    int mid=(l+r)>>1;
    if (pos<=mid) update(pos,v,opt,ls);
    else update(pos,v,opt,rs);
    pushup(o);
}

 // 从左到右的查询,对应lca->v的路径。
inline void query_ltr(int L,int R,int l,int r,int o,uint64_t& zero,uint64_t& one)
{
    if (L<=l && R>=r)
    {
        zero=(zero&f1[o])|((~zero)&f0[o]);
        one=(one&f1[o])|((~one)&f0[o]);
        return;
    }
    int mid=(l+r)>>1;
    if (L<=mid) query_ltr(L,R,ls,zero,one);
    if (R> mid) query_ltr(L,R,rs,zero,one);
}

 // 从右到左的查询,对应u->lca的路径
inline void query_rtl(int L,int R,int l,int r,int o,uint64_t& zero,uint64_t& one)
{
    if (L<=l && R>=r)
    {
        zero=(zero&g1[o])|((~zero)&g0[o]);
        one=(one&g1[o])|((~one)&g1[o]);
        return;
    }
    int mid=(l+r)>>1;
    if (R> mid) query_rtl(L,R,rs,zero,one);
    if (L<=mid) query_rtl(L,R,ls,zero,one);
}

inline int LCA(int u,int v)
{
    while (top[u]!=top[v])
    {
        if (depth[top[u]]<depth[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return depth[u]>depth[v]?v:u;
}

inline uint64_t query(int u,int v,uint64_t w,int n,int k)
{
    int endpos=v;
    static int stack[maxn];
    uint64_t zero=0,one=UINT64_MAX;
    int lca=LCA(u,v);
    while (top[u]!=top[lca])
    {
        query_rtl(id[top[u]],id[u],1,n,1,zero,one);
        u=fa[top[u]];
    } // 此时u和lca在一条重链上。
    if (u!=lca) query_rtl(id[top[u]]+1,id[u],1,n,1,zero,one); // 含lca的重链上除了u的节点
    int cnt=0;
    while (top[v]!=top[lca])
        stack[++cnt]=top[v],v=fa[top[v]];
    // stack是v到lca路径上所有的重链顶点
    // 计算lca那半条重链答案的贡献
    query_ltr(id[lca],id[v],1,n,1,zero,one);

    // 计算每条整条的重链的贡献 
    for (int i=cnt;i>1;--i)
        query_ltr(id[stack[i]],id[fa[stack[i-1]]],1,n,1,zero,one);
    // 计算v那半条重链的贡献
    if (cnt) query_ltr(id[stack[1]],id[endpos],1,n,1,zero,one);
    // 按位贪心,ans是我最初应该填的数
    uint64_t ans=0;
    for (int i=k-1;~i;--i)
    {
        if ((1ull<<i)>w) continue;
        if ((zero&(1ull<<i)) || !(one&(1ull<<i))) continue;
        else if ((ans|(1ull<<i))<=w) ans|=1ull<<i;
    }
    return (((~ans)&zero)|(ans&one))&(k==64?UINT64_MAX:(((1ull<<k))-1));
}

int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=n;++i)
        scanf("%d%lld",opr+i,w+i);
    for (int i=1,u,v;i<n;++i)
    {
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0,1);dfs(1,1);build(1,n,1);
    uint64_t z;
    for (int i=1,x,y,opt;i<=m;++i)
    {
        scanf("%d%d%d%llu",&opt,&x,&y,&z);
        if (opt&2) update(id[x],z,y,1,n,1);
        else printf("%llu\n",query(x,y,z,n,k));
    }
}

by lukelin @ 2019-05-09 19:21:39

@wycero 您确定是云南省选,云南有省选吗?
由乃oi真好玩


by _WA自动机 @ 2019-05-09 21:04:08

窝调出来了...谢谢各位,本帖终结..


by BinDir0 @ 2019-07-13 20:40:59

@_WA自动机 dalao您帮我看一下可好qwq?

https://www.luogu.org/recordnew/show/20755402


by BinDir0 @ 2019-07-13 20:56:59

@_WA自动机 不用了qwq调出来惹


by Spasmodic @ 2020-03-13 10:43:56

尻咕


上一页 |