【树链剖分】LGP3613 睡觉困难综合征

来源:互联网 发布:python 迭代器 定义 编辑:程序博客网 时间:2024/04/30 21:06

原题地址

【题目大意】
不想打了。

【题目分析】
每一位不会互相影响,可以把每一位分开考虑。
还要用unsigned long long。

【解题思路】

将每一位分开以后修改好啊,直接改就好了。
询问的时候算出来每一位填0,1经过这条链的变换之后得到的值。

我们发现从高位往低位走的时候,如果这一位填0可以得到1,那么填0一定是最优的。

否则如果可以填1,就把这一位填为1。

复杂度是nklog2n(树剖)或者nklogn(LCT),只能通过50%的数据

然后我们决定把这个k搞掉。
只要把k位一起算就可以了,多维护几个值就好。

复杂度是O(nklog2n)(树剖)或者O(nklogn)(LCT)

【代码】

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef unsigned long long ULL;const ULL mx=0-1;const int MAXN=2e5+10;int n,m,k,tot,sz;int opt[MAXN],siz[MAXN],dep[MAXN],q[MAXN],pos[MAXN];int head[MAXN],top[MAXN],son[MAXN],fa[MAXN];ULL val[MAXN],cf[MAXN];struct Tway{    int v,nex;};Tway e[MAXN<<1];struct Tree{    ULL v0,v1,w0,w1;};Tree tree[MAXN<<2],ans0[MAXN],ans1[MAXN];inline void add(int u,int v){    ++tot;    e[tot].v=v;e[tot].nex=head[u];head[u]=tot;}inline void dfs0(int u,int f){    siz[u]=1;dep[u]=dep[f]+1;    for(int i=head[u];i;i=e[i].nex)    {        int v=e[i].v;        if(v==f)            continue;        fa[v]=u;        dfs0(v,u);        siz[u]+=siz[v];        if(siz[v]>siz[son[u]])            son[u]=v;    }}inline void dfs1(int u,int tp){//  printf("%d\n",u);    top[u]=tp;pos[u]=++sz;q[sz]=u;    if(!son[u])        return;    dfs1(son[u],tp);    for(int i=head[u];i;i=e[i].nex)    {        int v=e[i].v;        if(v!=fa[u] && v!=son[u])            dfs1(v,v);    }}inline ULL calc(ULL num,int u){    if(opt[u]==1)   return num&val[u];    if(opt[u]==2)   return num|val[u];    if(opt[u]==3)   return num^val[u];}inline Tree update(Tree l,Tree r){    Tree tmp;    tmp.v0=tmp.v1=tmp.w0=tmp.w1=0;    tmp.v0=(l.v0 & r.v1) | ((~l.v0)&r.v0);    tmp.v1=(l.v1 & r.v1) | ((~l.v1)&r.v0);    tmp.w0=(r.w0 & l.w1) | ((~r.w0)&l.w0);    tmp.w1=(r.w1 & l.w1) | ((~r.w1)&l.w0);//typed wrong    return tmp;}inline void pushup(int rt){    tree[rt]=update(tree[rt<<1],tree[rt<<1|1]);}inline void build(int rt,int l,int r){    if(l==r)    {        int tmp=q[l];        tree[rt].v0=tree[rt].w0=calc(0,tmp);        tree[rt].v1=tree[rt].w1=calc(mx,tmp);        return;    }    int mid=(l+r)>>1;    build(rt<<1,l,mid);    build(rt<<1|1,mid+1,r);    pushup(rt);}inline void changep(int rt,int l,int r,int p){    if(l==r && l==p)    {        int tmp=q[l];        tree[rt].v0=tree[rt].w0=calc(0,tmp);        tree[rt].v1=tree[rt].w1=calc(mx,tmp);        return;    }    int mid=(l+r)>>1;    if(p<=mid)        changep(rt<<1,l,mid,p);    else        changep(rt<<1|1,mid+1,r,p);    pushup(rt);}inline Tree query(int rt,int l,int r,int L,int R){    if(L<=l && r<=R)        return tree[rt];    int mid=(l+r)>>1;    Tree ret;bool flag=false;    if(L<=mid)        ret=query(rt<<1,l,mid,L,R),flag=true;    if(R>mid)        if(flag)            ret=update(ret,query(rt<<1|1,mid+1,r,L,R));        else            ret=query(rt<<1|1,mid+1,r,L,R);    return ret;}inline Tree solve(int x,int y){    int cnt0=0,cnt1=0;    while(top[x]!=top[y])    {        if(dep[top[x]]>dep[top[y]])        {            ans0[++cnt0]=query(1,1,n,pos[top[x]],pos[x]);            x=fa[top[x]];        }        else        {            ans1[++cnt1]=query(1,1,n,pos[top[y]],top[y]);            y=fa[top[y]];        }    }    if(dep[x]>=dep[y])        ans0[++cnt0]=query(1,1,n,pos[y],pos[x]);    else        ans1[++cnt1]=query(1,1,n,pos[x],pos[y]);    for(int i=1;i<=cnt0;++i)        swap(ans0[i].v0,ans0[i].w0),swap(ans0[i].v1,ans0[i].w1);//swap false first    Tree sum;    if(cnt0)    {        sum=ans0[1];        for(int i=2;i<=cnt0;++i)            sum=update(sum,ans0[i]);        if(cnt1)            sum=update(sum,ans1[cnt1]);    }    else        sum=ans1[cnt1];    for(int i=cnt1-1;i>=1;--i)        sum=update(sum,ans1[i]);    printf("%d %d %d %d\n",sum.v0,sum.v1,sum.w0,sum.w1);    return sum;}int main(){    freopen("LGP3613.in","r",stdin);    freopen("LGP3613.out","w",stdout);    scanf("%d%d%d",&n,&m,&k);    cf[0]=1;    for(int i=1;i<=k-1;++i)        cf[i]=(cf[i-1]<<1);    for(int i=1;i<=n;++i)        scanf("%d%llu",&opt[i],&val[i]);    for(int i=1;i<n;++i)    {        int u,v;        scanf("%d%d",&u,&v);        add(u,v);add(v,u);    }    dfs0(1,0);dfs1(1,1);    build(1,1,n);    for(int i=1;i<=m;++i)    {        int op,u,v;ULL t;        scanf("%d%d%d%llu",&op,&u,&v,&t);        if(op&1)        {            Tree tmp=solve(u,v);ULL ret=0;            for(int i=63;i>=0;--i)            {                ULL t0=(tmp.v0>>i)&1;                ULL t1=(tmp.v1>>i)&1;                if(t0>=t1 || cf[i]>t)                    ret|=(t0 ? cf[i] : 0);                else                {                    ret|=(t1 ? cf[i] : 0);                    t-=cf[i];                }            }            printf("%llu\n",ret);        }        else        {            opt[u]=v;val[u]=t;            changep(1,1,n,pos[u]);        }    }    return 0;}