BZOJ4811: [Ynoi2017]由乃的OJ 重链剖分

题意:起床困难综合征出到树上,带单点修改和区间询问
很容易想到在线段树上维护每一位遍历所有操作后会变成什么,但是第一次交TLE了。。。
然后发现我以前写了假的《又是nand》。。。我说怎么跑得这么慢。。。
维护上面说的这个东西并不需要64*2个bool变量,而是可以压到两个unsigned long long里,分别代表每一位输入为0和每一位输入为1。
将两个合并:若输入为0,经过左变量后某些bit会变成1,这些bit在输出中与”若输入为1”的右变量那些bit保持一致,其余bit与”若输入为0”的右变量那些bit保持一致,可得:
c.x0=(a.x0&b.x1)|(~a.x0&b.x0)
另一个同理。c.x1=(a.x1&b.x1)|(~a.x1&b.x0)
于是树剖就可以维护了。得到信息后从高位到低位贪心能选就选。
代码:

#include<cstdio>
#include<cstring>
#define gm 100001
using namespace std;
typedef unsigned long long ll;
int n,m,k;
struct Istream
{
    static const size_t str=1<<16;
    char buf[str],*s,*t;
    Istream():buf(),s(),t(){}
    char get()
    {
        return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++);
    }
    Istream& operator >> (int &x)
    {
        register char c;
        do c=get(); while(c<'0'||c>'9');
        x=0;
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
        return *this;
    }
    Istream& operator>> (ll &x)
    {
        register char c;
        do c=get(); while(c<'0'||c>'9');
        x=0;
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
        return *this;
    }
}cin;
struct Ostream
{
    static const size_t str=1<<16;
    char buf[str],*s,*t;
    Ostream():buf(),s(buf),t(buf+str){}
    ~Ostream(){fwrite(buf,1,s-buf,stdout);}
    void put(char c)
    {
        (s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c);
    }
    Ostream& operator<< (ll x)
    {
        if(!x)
        {
            return put('0'),*this;
        }
        char a[22],t=1;
        while(x)
        a[t++]=x%10,x/=10;
        while(--t)
        put(a[t]+'0');
        return *this;
    }
    Ostream& operator<< (const char *x)
    {
        while(*x) put(*x++);
        return *this;
    }
}cout;
const char *endl="\n";
struct info
{
    ll a,b;
    info(){}
    info(const ll &x,int opt)
    {
        switch(opt)
        {
            case 1:
                a=0,b=x;
                break;
            case 2:
                a=x,b=~0ull;
                break;
            default:
                a=x,b=~x;
        }
    }
    info(const ll &a,const ll &b):a(a),b(b){}
    bool operator () (int x,int y)
    {
        return y?(b>>x&1ull):(a>>x&1ull);
    }
    info operator + (const info &v) const
    {
        return info((a&v.b)|(~a&v.a),(b&v.b)|(~b&v.a));
    }
}pre[262144],suf[262144],nil;
int op[gm];
ll val[gm];
ll pool[gm<<1],*ptr=pool;
struct e
{
    int t;
    e *n;
    e(int t,e *n):t(t),n(n){}
    inline void* operator new(size_t){return ++ptr;}
}*f[gm];
int sz[gm],fa[gm],son[gm],dfn[gm],dep[gm],top[gm],ord[gm],ct=0;
void dfs1(int x=1)
{
    sz[x]=1;
    for(e *i=f[x];i;i=i->n)
    {
        if(i->t==fa[x]) continue;
        fa[i->t]=x;
        dep[i->t]=dep[x]+1;
        dfs1(i->t);
        sz[x]+=sz[i->t];
        if(sz[i->t]>=sz[son[x]]) son[x]=i->t;
    }
}
void dfs2(int x=1)
{
    ord[dfn[x]=++ct]=x;
    top[x]=(x==son[fa[x]]?top[fa[x]]:x);
    if(son[x]) dfs2(son[x]);
    for(e *i=f[x];i;i=i->n)
    {
        if(i->t==fa[x]||i->t==son[x]) continue;
        dfs2(i->t);
    }
}
void build(int l=1,int r=n,int o=1)
{
    if(l==r)
    {
        pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]);
        return;
    }
    int mid=l+r>>1,ls=o<<1,rs=ls|1;
    build(l,mid,ls);
    build(mid+1,r,rs);
    pre[o]=pre[ls]+pre[rs];
    suf[o]=suf[rs]+suf[ls];
}
int x,y;
void cast(int l=1,int r=n,int o=1)
{
    if(l==r)
    {
        pre[o]=suf[o]=info(val[ord[l]],op[ord[l]]);
        return;
    }
    int mid=l+r>>1,ls=o<<1,rs=ls|1;
    if(x<=mid) cast(l,mid,ls);
    else cast(mid+1,r,rs);
    pre[o]=pre[ls]+pre[rs];
    suf[o]=suf[rs]+suf[ls];
}
info getpr(int l=1,int r=n,int o=1)
{
    if(x<=l&&r<=y)
    {
        return pre[o];
    }
    int mid=l+r>>1,ls=o<<1,rs=ls|1;
    if(y<=mid) return getpr(l,mid,ls);
    if(mid<x) return getpr(mid+1,r,rs);
    return getpr(l,mid,ls)+getpr(mid+1,r,rs);
}
info getsf(int l=1,int r=n,int o=1)
{
    if(x<=l&&r<=y)
    {
        return suf[o];
    }
    int mid=l+r>>1,ls=o<<1,rs=ls|1;
    if(y<=mid) return getsf(l,mid,ls);
    if(mid<x) return getsf(mid+1,r,rs);
    return getsf(mid+1,r,rs)+getsf(l,mid,ls);
}   
int LCA(int a,int b)
{
    while(top[a]!=top[b])
    {
        if(dep[top[a]]<dep[top[b]]) a^=b^=a^=b;
        a=fa[top[a]];
    }
    return dep[a]<dep[b]?a:b;
}
info query(int a,int b)
{
    int lca=LCA(a,b);
    info ra=nil,rb=nil,res;
    while(top[a]!=top[lca])
    {
        x=dfn[top[a]],y=dfn[a];
        ra=ra+getsf();
        a=fa[top[a]];
    }
    x=dfn[lca],y=dfn[a];
    ra=ra+getsf();
    while(top[b]!=top[lca])
    {
        x=dfn[top[b]],y=dfn[b];
        rb=getpr()+rb;
        b=fa[top[b]];
    }
    if(b!=lca)
    {
        x=dfn[lca]+1,y=dfn[b];
        rb=getpr()+rb;
    }
    return ra+rb;
}
int main()
{
    cin>>n>>m>>k;
    nil.a=0,nil.b=(k==64?~0ull:(1ull<<k)-1);
    for(int i=1;i<=n;++i)
    cin>>op[i]>>val[i];
    for(int i=1;i<n;++i)
    {
        int u,v;
        cin>>u>>v;
        f[u]=new e(v,f[u]);
        f[v]=new e(u,f[v]);
    }
    dfs1(),dfs2(),build();
    for(int i=1;i<=m;++i)
    {
        int tp,x,y;
        ll z;
        cin>>tp>>x>>y>>z;
        if(tp==1)
        {
            info res=query(x,y);
            ll ans=0,kre=0;
            for(int i=k-1;~i;--i)
            {
                if(res(i,0)) ans|=1ull<<i;
                else if(res(i,1)&&(kre|(1ull<<i))<=z)
                kre|=1ull<<i,ans|=1ull<<i;
            }
            cout<<ans<<endl;
        }
        else
        {
            op[x]=y,val[x]=z;
            ::x=dfn[x];
            cast();
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值