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;
    }
  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/Gloid/p/9986228.html
Copyright © 2011-2022 走看看