zoukankan      html  css  js  c++  java
  • BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)

      先考虑NOI2014的水题,显然从高位到低位贪心,算一下该位取0和1分别得到什么即可。

      加强这个水题,变成询问区间。那么线段树维护该位取0和1从左到右和从右到左走完这个节点表示的区间会变成什么即可,也滋磁修改了。

      然后上树,显然树剖即可。非常惨的变成了O(nklog2n)。压一下位就不惨了,变成O(n(k+log2n))。

      树剖lca都能写挂调一天,不会熟练剖分,退役了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll unsigned long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    ll read()
    {
        ll x=0;char c=getchar();
        while (c<'0'||c>'9') c=getchar();
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x;
    }
    ll b[N],gor[N<<2][2],gol[N<<2][2],inf,I;
    int n,m,k,a[N],p[N],t,cnt;
    int id[N],dfn[N],top[N],fa[N],son[N],size[N],deep[N];
    int L[N<<2],R[N<<2];
    struct data{int to,nxt;
    }edge[N<<1];
    struct data2{ll x,y;};
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k)
    {
        size[k]=1;
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=fa[k])
        {
            fa[edge[i].to]=k;
            deep[edge[i].to]=deep[k]+1;
            dfs(edge[i].to);
            size[k]+=size[edge[i].to];
            if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
        }
    }
    void dfs2(int k,int from)
    {
        top[k]=from;dfn[k]=++cnt;id[cnt]=k;
        if (son[k]) dfs2(son[k],from);
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) dfs2(edge[i].to,edge[i].to);
    }
    ll trans1(ll x,int op,ll y){if (op==1) return x&y;if (op==2) return x|y;return x^y;}
    ll trans(ll x,ll t0,ll t1){return (x&t1)|((~x)&t0);}
    void up(int k)
    {
        gor[k][0]=trans(gor[k<<1][0],gor[k<<1|1][0],gor[k<<1|1][1]);
        gor[k][1]=trans(gor[k<<1][1],gor[k<<1|1][0],gor[k<<1|1][1]);
        gol[k][0]=trans(gol[k<<1|1][0],gol[k<<1][0],gol[k<<1][1]);
        gol[k][1]=trans(gol[k<<1|1][1],gol[k<<1][0],gol[k<<1][1]);
    }
    void build(int k,int l,int r)
    {
        L[k]=l,R[k]=r;
        if (l==r) {gol[k][0]=gor[k][0]=trans1(0,a[id[l]],b[id[l]]);gol[k][1]=gor[k][1]=trans1(inf,a[id[l]],b[id[l]]);return;}
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k);
    }
    void modify(int k,int x,int op,ll y)
    {
        if (L[k]==R[k]) {gol[k][0]=gor[k][0]=trans1(0,op,y);gol[k][1]=gor[k][1]=trans1(inf,op,y);return;}
        int mid=L[k]+R[k]>>1;
        if (x<=mid) modify(k<<1,x,op,y);
        else modify(k<<1|1,x,op,y);
        up(k);
    }
    data2 queryl(int k,int l,int r)
    {
        if (L[k]==l&&R[k]==r) return (data2){gol[k][0],gol[k][1]};
        int mid=L[k]+R[k]>>1;
        if (r<=mid) return queryl(k<<1,l,r);
        else if (l>mid) return queryl(k<<1|1,l,r);
        else
        {
            data2 x=queryl(k<<1|1,mid+1,r),y=queryl(k<<1,l,mid);
            return (data2){trans(x.x,y.x,y.y),trans(x.y,y.x,y.y)};
        }
    }
    data2 queryr(int k,int l,int r)
    {
        if (L[k]==l&&R[k]==r) return (data2){gor[k][0],gor[k][1]};
        int mid=L[k]+R[k]>>1;
        if (r<=mid) return queryr(k<<1,l,r);
        else if (l>mid) return queryr(k<<1|1,l,r);
        else
        {
            data2 x=queryr(k<<1,l,mid),y=queryr(k<<1|1,mid+1,r);
            return (data2){trans(x.x,y.x,y.y),trans(x.y,y.x,y.y)};
        }
    }
    void solve(ll &t0,ll &t1,int x,int lca)
    {
        if (top[x]==top[lca])
        {
            data2 t=queryr(1,dfn[lca],dfn[x]);
            t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
            return;
        }
        solve(t0,t1,fa[top[x]],lca);
        data2 t=queryr(1,dfn[top[x]],dfn[x]);
        t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
    }
    ll jump_query(int x,int y,ll z)
    {
        ll t0=0,t1=inf;data2 t;int lca=0,P=x,Q=y;
        while (top[P]!=top[Q])
        {
            if (deep[top[P]]<deep[top[Q]]) swap(P,Q);
            P=fa[top[P]];
        }
        if (deep[P]<deep[Q]) swap(P,Q);
        lca=Q;
        while (top[x]!=top[lca])
        {
            t=queryl(1,dfn[top[x]],dfn[x]);
            t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
            x=fa[top[x]];
        }
        if (lca!=x)
        {
            for (int i=p[lca];i;i=edge[i].nxt)
            if (dfn[edge[i].to]>dfn[lca]&&dfn[edge[i].to]<=dfn[x]) {t=queryl(1,dfn[edge[i].to],dfn[x]);break;}
            t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
        }
        solve(t0,t1,y,lca);
        ll s=0,c=0;
        for (int i=k-1;~i;i--)
        if (t0&(I<<i)) s+=I<<i;
        else if ((t1&(I<<i))&&c+(I<<i)<=z) c+=I<<i,s+=I<<i;
        return s;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4811.in","r",stdin);
        freopen("bzoj4811.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),k=read();inf=I=1;for (int i=1;i<=k;i++) inf<<=1;inf--;
        for (int i=1;i<=n;i++) a[i]=read(),b[i]=read();
        for (int i=1;i<n;i++)
        {
            int x=read(),y=read();
            addedge(x,y),addedge(y,x);
        }
        dfs(1);
        dfs2(1,1);
        build(1,1,n);
        while (m--)
        {
            int op=read(),x=read(),y=read();ll z=read();
            if (op==1) printf("%llu
    ",jump_query(x,y,z));
            else modify(1,dfn[x],y,z);
        }
        return 0;
    }
  • 相关阅读:
    ASP.Net 显示
    ASP.Net EF框架
    ASP.Net redis存取方法
    ASP.Net 红包
    winform 代码生成textbox ,checkbox
    c# winform 窗体 对话框绑定的值如何填到主窗体问题
    c# / .net wFramework winform 之运行后的窗体窗口可拖动操作
    托管调试助手 "DisconnectedContext":“针对此 RuntimeCallableWrapper 向 COM 上下文 0xd47808 的转换失败,错误如下: 系统调用失败。
    使用C#语言,如何实现EPLAN二次开发 Api插件及菜单展示
    winform 学习之qq邮箱正则验证及常用正则
  • 原文地址:https://www.cnblogs.com/Gloid/p/9986228.html
Copyright © 2011-2022 走看看