题解:

对于每一个节点,我们建立v0,v1

v0表示0进过会怎么样

v1表示1进过会怎么样

然后线段树合并

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100005;
typedef unsigned long long ull;
ull a[N],zz,now,ans;
int n,m,k,op,xx,yy,Op[N],fi[N],ne[N*2],v[N*2],tot;
int size[N],fa[N],son[N],deep[N],rev[N],dfn[N],cnt,top[N];
struct Tree
{
    ull v0,v1;Tree(){}
    Tree(int op,ull x)
     {
         if (op==1)v0=0,v1=x;
        else if (op==2)v0=x,v1=~0;
        else v0=x,v1=(~0)^x;
     }
    Tree(ull x,ull y){v0=x,v1=y;}
}trl[N*8],trr[N*8];
Tree operator+(Tree x,Tree y)
{
    return Tree((x.v0&y.v1)|((~x.v0)&y.v0),(x.v1&y.v1)|((~x.v1)&y.v0));
}
void jb(int x,int y)
{
    v[tot]=y;
    ne[tot]=fi[x];
    fi[x]=tot++;
}
void dfs1(int x)
{
    size[x]=1;
    for (int i=fi[x];~i;i=ne[i])
     if (v[i]!=fa[x])
      {
        fa[v[i]]=x;
        deep[v[i]]=deep[x]+1;
        dfs1(v[i]);
        size[x]+=size[v[i]];
        if (size[v[i]]>size[son[x]])son[x]=v[i];
      }
}
void dfs2(int x,int tp)
{
    rev[dfn[x]=++cnt]=x;
    top[x]=tp;
    if (son[x])dfs2(son[x],tp);
    for (int i=fi[x];~i;i=ne[i])
     if (v[i]!=fa[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
}
void build(int l,int r,int pos)
{
    if (l==r)
     {
         trl[pos]=trr[pos]=Tree(Op[rev[l]],a[rev[l]]);
        return;
      }
    int mid=(l+r)>>1;
    build(l,mid,pos*2);
    build(mid+1,r,pos*2+1);
    trl[pos]=trl[pos*2]+trl[pos*2+1];
    trr[pos]=trr[pos*2+1]+trr[pos*2];
}
void insert(int l,int r,int pos,int num)
{
    if (l==r)
     {
         trl[pos]=trr[pos]=Tree(Op[rev[l]],a[rev[l]]);
        return;
     }
    int mid=(l+r)>>1;
    if (mid<num)insert(mid+1,r,pos*2+1,num);
    else insert(l,mid,pos*2,num);
    trl[pos]=trl[pos*2]+trl[pos*2+1];
    trr[pos]=trr[pos*2+1]+trr[pos*2];
}
Tree query(int l,int r,int pos,int L,int R,int f)
{
    if (l>=L&&r<=R)return f?trr[pos]:trl[pos];
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if (mid<L)return query(mid+1,r,pos*2+1,L,R,f);
    if (mid>=R)return query(l,mid,pos*2,L,R,f);
    if (!f)return query(l,mid,pos*2,L,R,f)+query(mid+1,r,pos*2+1,L,R,f);
    return query(mid+1,r,pos*2+1,L,R,f)+query(l,mid,pos*2,L,R,f);
}
Tree solve(int x,int y)
{
    Tree vx=Tree((int)3,0ull),vy=Tree((int)3,0ull);
    int fx=top[x],fy=top[y];
    while (fx!=fy)
     if (deep[fx]>deep[fy])
      {
          vx=vx+query(1,n,1,dfn[fx],dfn[x],1);
        x=fa[fx];
        fx=top[x];
      }
     else 
      {    
          vy=query(1,n,1,dfn[fy],dfn[y],0)+vy;
        y=fa[fy];
        fy=top[y];
      }
    if (deep[x]>deep[y])return vx+query(1,n,1,dfn[y],dfn[x],1)+vy;
    return vx+query(1,n,1,dfn[x],dfn[y],0)+vy;
}
int main()
{
    memset(fi,-1,sizeof(fi));
    deep[1]=1;
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=n;i++)scanf("%d%llu",&Op[i],&a[i]);
    for (int i=1;i<n;i++)
     {
         scanf("%d%d",&xx,&yy);
        jb(xx,yy);jb(yy,xx);
     }
    dfs1(1);dfs2(1,1); 
    build(1,n,1);
    while (m--)
     {
        scanf("%d%d%d%llu",&op,&xx,&yy,&zz);
        if (op==2)Op[xx]=yy,a[xx]=zz,insert(1,n,1,dfn[xx]);
        else
         {
             Tree t=solve(xx,yy);now=ans=0;
            for (int i=k-1;~i;i--)
             if (t.v0&(1ull<<i))ans+=1ull<<i;
             else if (t.v1&(1ull<<i)&&now+(1ull<<i)<=zz)
              {
                  now+=1ull<<i;
                ans+=1ull<<i;
              }
            printf("%llu\n",ans);
         }
     }
    return 0; 
}

 

posted on 2017-12-09 09:59  宣毅鸣  阅读(223)  评论(0编辑  收藏  举报