首页 > 代码库 > [洛谷]P3613 睡觉困难综合征

[洛谷]P3613 睡觉困难综合征

题目大意:给出一棵n个点的树,每个点有一个运算符(与、或、异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对路径上经过的点做对应的运算,最终最大能是多少。(n,操作数<=100,000,数字在[0,2^64)之间)

思路:洛谷改编NOI的一道神题,树剖/LCT维护若一开始全是0/全是1,经过一条链后各位会变成什么,用位运算合并信息,然后每个询问,从高位往低位贪心,每次取0和1中经过这条链后得到的较大值,若相同则取0,总复杂度O(nlogn)/O(nlogn^2)。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll unsigned long long
inline ll read()
{
    ll x;char c;
    while((c=getchar())<0||c>9);
    for(x=c-0;(c=getchar())>=0&&c<=9;)x=(x<<3)+(x<<1)+c-0;
    return x;
}
#define MN 100000
#define L(x) c[x][0]
#define R(x) c[x][1]
struct edge{int nx,t;}e[MN*2+5];
struct data{ll f[2];}lf[MN+5],rf[MN+5],f[MN+5];
data operator+(const data&a,const data&b)
{
    return (data){~a.f[0]&b.f[0]|a.f[0]&b.f[1],
                  ~a.f[1]&b.f[0]|a.f[1]&b.f[1]};
}
int h[MN+5],en,fa[MN+5],c[MN+5][2],rv[MN+5],z[MN+5],zn;
inline void ins(int x,int y)
{
    e[++en]=(edge){h[x],y};h[x]=en;
    e[++en]=(edge){h[y],x};h[y]=en;
}
void dfs(int x)
{
    for(int i=h[x];i;i=e[i].nx)
        if(e[i].t!=fa[x])fa[e[i].t]=x,dfs(e[i].t);
}
inline void up(int x)
{
    lf[x]=rf[x]=f[x];
    if(L(x))lf[x]=lf[L(x)]+lf[x],rf[x]=rf[x]+rf[L(x)];
    if(R(x))lf[x]=lf[x]+lf[R(x)],rf[x]=rf[R(x)]+rf[x];
}
void init(int x,int o,ll z)
{
    if(o==1)f[x]=(data){0,z};
    if(o==2)f[x]=(data){z,-1};
    if(o==3)f[x]=(data){z,~z};
    up(x);
}
inline void rev(int x){rv[x]^=1;swap(L(x),R(x));swap(lf[x],rf[x]);}
inline void down(int x){if(rv[x])rev(L(x)),rev(R(x)),rv[x]=0;}
inline bool isc(int x){return L(fa[x])==x||R(fa[x])==x;}
void rotate(int x)
{
    int f=fa[x],ff=fa[f],l=R(f)==x,r=l^1;
    if(isc(f))c[ff][R(ff)==f]=x;
    fa[f]=x;fa[x]=ff;fa[c[x][r]]=f;
    c[f][l]=c[x][r];up(c[x][r]=f);
}
void splay(int x)
{
    for(int i=z[zn=1]=x;isc(i);)i=z[++zn]=fa[i];
    for(;zn;--zn)down(z[zn]);
    for(int f;isc(x);rotate(x))
        if(isc(f=fa[x]))rotate(L(fa[f])==f^L(f)==x?x:f);
    up(x);
}
void access(int x)
{
    for(int i=0;x;x=fa[i=x])splay(x),R(x)=i;
}
int main()
{
    int n,m,i,x,u;ll z,ans,f0,f1;
    n=read();m=read();read();
    for(i=1;i<=n;++i)x=read(),init(i,x,read());
    for(i=1;i<n;++i)ins(read(),read());
    dfs(1);
    while(m--)
        if(read()<2)
        {
            access(x=read());splay(x);rev(x);
            access(x=read());splay(x);
            z=read();ans=u=0;
            for(i=64;i--;)
                if(u||(z&(1LLU<<i)))
                {
                    f0=lf[x].f[0]&(1LLU<<i);
                    f1=lf[x].f[1]&(1LLU<<i);
                    if(f0>=f1)u=1;
                    ans|=max(f0,f1);
                }
                else ans|=lf[x].f[0]&(1LLU<<i);
            printf("%llu\n",ans);
        }
        else x=read(),i=read(),splay(x),init(x,i,read());
}

 

[洛谷]P3613 睡觉困难综合征