bzoj 4811: [Ynoi2017]由乃的OJ

树链剖分,用zkw线段树维护每条链两个方向上对每一位的变换情况,由于位数较少,可以用两个unsigned long long表示

#include<cstdio>
typedef unsigned long long u64;
const int N=100007;
char buf[N*100],*ptr=buf-1;
int _(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
u64 _u64(){
    u64 x=0;
    int c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
int es[N*2],enx[N*2],e0[N],ep=2,tp[N];
u64 v[N];
int fa[N],sz[N],top[N],dep[N],son[N],id[N],idp=0,idr[N];
int n,m,k;
u64 vs[262777][4];
void f1(int w,int pa){
    dep[w]=dep[fa[w]=pa]+1;
    sz[w]=1;
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(u!=pa){
            f1(u,w);
            sz[w]+=sz[u];
            if(sz[u]>sz[son[w]])son[w]=u;
        }
    }
}
void f2(int w,int tp){
    top[w]=tp;
    id[w]=++idp;
    idr[idp]=w;
    if(son[w])f2(son[w],tp);
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(u!=fa[w]&&u!=son[w])f2(u,u);
    }
}
int s1[107],p1,s2[107],p2,s3[10007],s4[10007],p3,p4;
void find(int l,int r,int tp){
    p1=p2=0;
    for(l+=131071,r+=131073;r-l!=1;l>>=1,r>>=1){
        if(~l&1)s1[p1++]=l^1;
        if(r&1)s2[p2++]=r^1;
    }
    if(!tp){
        for(int i=0;i<p2;++i)s4[p4++]=s2[i];
        while(p1)s4[p4++]=s1[--p1];
    }else{
        for(int i=0;i<p2;++i)s3[p3++]=s2[i];
        while(p1)s3[p3++]=s1[--p1];
    }
}
#define cal(a,b,c0,c1) (a)=((~(b)&(c0))|((b)&(c1)))
void init(int w,int tp,u64 v){
    u64*a=vs[w];
    if(tp==1){
        a[0]=a[2]=0ll&v;
        a[1]=a[3]=-1ll&v;
    }else if(tp==2){
        a[0]=a[2]=0ll|v;
        a[1]=a[3]=-1ll|v;
    }else if(tp==3){
        a[0]=a[2]=0ll^v;
        a[1]=a[3]=-1ll^v;
    }
}
void up(u64*a,u64*l,u64*r){
    cal(a[0],l[0],r[0],r[1]);
    cal(a[1],l[1],r[0],r[1]);
    cal(a[2],r[2],l[2],l[3]);
    cal(a[3],r[3],l[2],l[3]);
}
u64 _v0,_v1;
void get(int x,int y){
    p3=p4=0;
    int a=top[x],b=top[y];
    while(a!=b){
        if(dep[a]>dep[b]){
            find(id[a],id[x],0);
            x=fa[a],a=top[x];
        }else{
            find(id[b],id[y],1);
            y=fa[b],b=top[y];
        }
    }
    if(dep[x]>dep[y]){
        find(id[y],id[x],0);
    }else{
        find(id[x],id[y],1);
    }
    u64 v0=0ll,v1=-1ll;
    for(int i=0;i<p4;++i){
        u64*a=vs[s4[i]];
        cal(v0,v0,a[2],a[3]);
        cal(v1,v1,a[2],a[3]);
    }
    while(p3){
        u64*a=vs[s3[--p3]];
        cal(v0,v0,a[0],a[1]);
        cal(v1,v1,a[0],a[1]);
    }
    _v0=v0,_v1=v1;
}
int main(){
    fread(buf,1,sizeof(buf),stdin)[buf]=0;
    n=_();m=_();k=_();
    for(int i=1;i<=n;++i){
        tp[i]=_();
        v[i]=_u64();
    }
    for(int i=1,a,b;i<n;++i){
        a=_();b=_();
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
    }
    f1(1,0);f2(1,1);
    for(int i=1;i<=n;++i)init(id[i]+131072,tp[i],v[i]);
    for(int i=131071;i;--i)up(vs[i],vs[i<<1],vs[i<<1|1]);
    for(int i=0;i<m;++i){
        int o=_(),x=_(),y=_();
        u64 z=_u64();
        if(o==1){
            get(x,y);
            u64 r=0,r0,r1;
            for(int i=63;i>=0;--i)if((r|1llu<<i)<=z){
                cal(r0,r,_v0,_v1);
                cal(r1,(r|1llu<<i),_v0,_v1);
                if(r0<r1)r|=1llu<<i;
            }
            cal(r0,r,_v0,_v1);
            printf("%llu\n",r0);
        }else{
            init(id[x]+131072,tp[x]=y,v[x]=z);
            for(int w=id[x]+131072>>1;w!=1;w>>=1)up(vs[w],vs[w<<1],vs[w<<1^1]);
        }
    }
    return 0;
}
时间: 2024-12-05 01:31:59

bzoj 4811: [Ynoi2017]由乃的OJ的相关文章

BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

3595: [Scoi2014]方伯伯的OjTime Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status] Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-",一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为1 x y,意味着将编号为z的用户编号改为V,而排名不变,执行完该操作后需要

【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树

[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名.由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由乃心情非常不好,因为Deus天天问她题...因为Deus天天问由乃OI题,所以由乃去学习了一下OI,由于由乃智商挺高,所以OI学的特别熟练她在RBOI2016中以第一名的成绩进入省队,参加了NOI2016获得了金牌保送 Deus:这个题怎么做

BZOJ4811 [Ynoi2017]由乃的OJ

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! 题目链接:BZOJ4811 正解:树链剖分+线段树 解题报告: 因为位与位之间互相独立,考虑直观做法,对于每一位维护两个变量,分别表示这一位输入$0$.$1$之后会变成的值. 这个复杂度是$O(knlog^2n)$,显然不能通过. 但是我们不难发现,对于不

【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并

题目描述 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号 排名.由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由乃心情非常不好,因为Deus天 天问她题...因为Deus天天问由乃OI题,所以由乃去学习了一下OI,由于由乃智商挺高,所以OI学的特别熟练她 在RBOI2016中以第一名的成绩进入省队,参加了NOI2016获得了金牌保送 Deus:这个题怎么做呀? yuno:这个不是NOI2014的水题吗... Deu

bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+贪心+二进制

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4811 题解 我现在为什么都写一题,调一天啊,马上真的退役不花一分钱了. 考虑这道题的弱化版 NOI2014 起床困难综合证的做法. 分成每一位来考虑,如果高位可以是 \(1\) 的话,那么尽量让高位为 \(1\). 求出当前位为 \(0/1\) 时,最终得到的是 \(0\) 还是 \(1\).因为要保证选的数小于 \(z\),所以对于都可以得到 \(1\) 的情况,尽量选择 \(0\) 可以

[BZOJ]4810: [Ynoi2017]由乃的玉米田

Time Limit: 30 Sec  Memory Limit: 256 MB Description 由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3选出的这两个

bzoj 4866: [Ynoi2017]由乃的商场之旅

设第i个字母的权值为1<<i,则一个可重集合可以重排为回文串,当且仅当这个集合的异或和x满足x==x&-x,用莫队维护区间内有多少对异或前缀和,异或后满足x==x&-x,这样端点移动的代价为字符集大小+1=27,因此时间复杂度为$O(27n\sqrt{m})$ #include<cstdio> #include<cmath> #include<algorithm> char buf[3000000],*ptr=buf-1; int _(){

BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分 位运算

原文链接 题目传送门 - BZOJ4811 题意概括 是BZOJ3668长在树上并加上修改和区间询问. 一棵树,n个节点,每一个节点有一个位运算符和一个运算数. 现在要你支持两种操作: 1. 单点修改. 2. 现在你有一个数字v,让他从x走到y,每到达一个节点进行相应的运算.v在0~z之间,让你使得运算结果最大,问v为何值. 题解 我们考虑树链剖分+线段树. 假设某一位为0或者1,那么经过一定的操作之后也是0或1. 那么,如果只有一位,那么两段就可以轻松合并了. k位也是一样,我们只需要用一堆奇

bzoj 4810: [Ynoi2017]由乃的玉米田 莫队 bitset

bitset大概就是让你轻松建立一个很长的二进制数来存东西,并提供了快捷的操作和优美的常数. #include <bitset> bitset <32> b;32为长度 需要引用头文件,定义一个bitset. stl的东西,所以从0开始. 支持左右移. 支持下标访问修改. b.any() b中是否存在置为1的二进制位 b.none() b中不存在置为1的二进制位 b.count() b中置为1的二进制位的个数 b.size() b中二进制位的个数 b[pos] 访问b中在pos处的