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\n";
#else
    const char LL[]="%lld\n";
#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\n",jump_query(x,y,z));
        else modify(1,dfn[x],y,z);
    }
    return 0;
}

 

posted @ 2018-11-20 18:42  Gloid  阅读(153)  评论(0编辑  收藏  举报