• bzoj4811[Ynoi2017]由乃的OJ


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4811

    第一次写树链剖分。搞清楚原树的点和线段树上的点的对应关系很重要。

      (树链剖分之所以能对应到线段树上,是因为走的不是重链就是点,都是dfs序连续区间。)

    本题有64位,不用像“睡觉困难综合征”那样每一位循环,弄到unsigned long long里就能一起弄。

      注意一下合并,想想就能明白。还要注意方向。

    感觉是一道很好的模板题。抄了TJ的代码,觉得写得好好。(https://blog.csdn.net/a1799342217/article/details/78818480)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ull unsigned long long
    using namespace std;
    const int N=1e5+5;
    int n,m,lm,head[N],xnt,tot,top[N],fa[N],dep[N],id[N],rnk[N],son[N],siz[N];
    ull op[N][2];
    struct Dt{
        ull p0,p1;//都是ull! 
    };
    struct Edge{
        int next,to;
        Edge(int n=0,int t=0):next(n),to(t) {}
    }edge[N<<1];
    struct Node{
        int l,r,ls,rs;
        Dt fr,fl;
    }a[N<<1];
    void added(int x,int y)
    {
        edge[++xnt]=Edge(head[x],y);head[x]=xnt;
        edge[++xnt]=Edge(head[y],x);head[y]=xnt;
    }
    void dfs1(int cr,int depth)
    {
        dep[cr]=depth;siz[cr]=1;
        for(int i=head[cr],v;i;i=edge[i].next)
            if((v=edge[i].to)!=fa[cr])
            {
                fa[v]=cr;dfs1(v,depth+1);siz[cr]+=siz[v];
                if(siz[v]>siz[son[cr]])son[cr]=v;
            }
    }
    void dfs2(int cr)
    {
        id[cr]=++tot;rnk[tot]=cr;
        if(!son[cr])return;
        top[son[cr]]=top[cr],dfs2(son[cr]);
        for(int i=head[cr],v;i;i=edge[i].next)
            if((v=edge[i].to)!=son[cr]&&v!=fa[cr])
            {
                top[v]=v;dfs2(v);
            }
    }
    Dt updt(ull op,ull w)
    {
        Dt ret;
        if(op==1)ret.p0=0&w,ret.p1=(~0)&w;
        if(op==2)ret.p0=0|w,ret.p1=(~0)|w;
        if(op==3)ret.p0=0^w,ret.p1=(~0)^w;
        return ret;
    }
    Dt pshp(Dt x,Dt y)
    {
        Dt ret;
        ret.p0=(x.p0&y.p1)|(~x.p0&y.p0);
        ret.p1=(x.p1&y.p1)|(~x.p1&y.p0);
        return ret;
    }
    void build(int l,int r,int cr)
    {
        a[cr].l=l;a[cr].r=r;
        if(l==r){a[cr].fl=a[cr].fr=updt(op[rnk[l]][0],op[rnk[l]][1]);return;}//rnk[l]!
        int mid=l+r>>1;
        tot++;a[cr].ls=tot;
        build(l,mid,tot);
        tot++;a[cr].rs=tot;
        build(mid+1,r,tot);
        a[cr].fl=pshp(a[a[cr].ls].fl,a[a[cr].rs].fl);
        a[cr].fr=pshp(a[a[cr].rs].fr,a[a[cr].ls].fr);
    }
    void mdfy(int cr,int x,ull op,ull w)
    {
        if(a[cr].l==a[cr].r)
        {
            a[cr].fl=a[cr].fr=updt(op,w);return;
        }
        int mid=a[cr].l+a[cr].r>>1;
        if(x<=mid)mdfy(a[cr].ls,x,op,w);
        else mdfy(a[cr].rs,x,op,w);
        a[cr].fl=pshp(a[a[cr].ls].fl,a[a[cr].rs].fl);
        a[cr].fr=pshp(a[a[cr].rs].fr,a[a[cr].ls].fr);
    }
    Dt srch(int cr,int l,int r,int fx)
    {
        if(a[cr].l>=l&&a[cr].r<=r)
            if(fx)return a[cr].fr;
            else return a[cr].fl;
        int mid=a[cr].l+a[cr].r>>1;//a[cr].l a[cr].r  !l !r
        if(mid>=r)return srch(a[cr].ls,l,r,fx);
        else if(mid<l)return srch(a[cr].rs,l,r,fx);
        else return pshp(srch(fx?a[cr].rs:a[cr].ls,l,r,fx),srch(fx?a[cr].ls:a[cr].rs,l,r,fx));
    }
    Dt find(int x,int y)
    {
        Dt ans1=updt(3,0),ans2=updt(3,0);
        while(top[x]!=top[y])
            if(dep[top[x]]>dep[top[y]])
            {
                ans1=pshp(ans1,srch(1,id[top[x]],id[x],1));//1(区间是从上到下,故从右可接上当前)
                x=fa[top[x]];
            }
            else
            {
                ans2=pshp(srch(1,id[top[y]],id[y],0),ans2);
                y=fa[top[y]];
            }
        if(dep[x]<=dep[y])return pshp(pshp(ans1,srch(1,id[x],id[y],0)),ans2);
        else return pshp(pshp(ans1,srch(1,id[y],id[x],1)),ans2);//1
    }
    void query(int x,int y,ull z)
    {
        Dt ans=find(x,y);ull ret=0,sum=0;
        for(int i=lm-1;i>=0;i--)
            if((1ull<<i)&ans.p0)ret|=(1ull<<i);
            else if(((1ull<<i)&ans.p1)&&(sum|(1ull<<i))<=z)
                sum|=(1ull<<i),ret|=(1ull<<i);
        printf("%llu
    ",ret);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&lm);
        for(int i=1;i<=n;i++)scanf("%llu%llu",&op[i][0],&op[i][1]);
        int x,y;
        for(int i=1;i<n;i++)scanf("%d%d",&x,&y),added(x,y);
        dfs1(1,1);top[1]=1;dfs2(1);tot=1;build(1,n,1);
        ull z;int q;
        while(m--)
        {
            scanf("%d%d%d%llu",&q,&x,&y,&z);
            if(q==2)mdfy(1,id[x],y,z);/////id[x]
            else query(x,y,z);
        }
        return 0;
    }
  • 相关阅读:
    openOPC与监控页面二
    Node教程——Gulp前端构建工具-教程
    回到顶部插件
    《软件测试52讲》——测试基础知识篇
    计算贝塞尔曲线上点坐标
    少年,不要滥用箭头函数啊
    JS属性defer
    leetcode-572-另一个树的子树
    leetcode-9.-回文数
    leetcode-300-最长上升子序列
  • 原文地址:https://www.cnblogs.com/Narh/p/9171362.html
Copyright © 2020-2023  润新知