题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4811

因为位运算的结果有可合并性,所以可以树链剖分,线段树维护;

细节很多,特别要注意从左往右运算和从右往左计算是不同的,在不同条件下一定要区分!!!

这篇博客写得很好(我就是模仿它写的):https://blog.csdn.net/a1799342217/article/details/78818480

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
int const maxn=;
int n,m,p,in[maxn],id[maxn],to[maxn],tp[maxn],head[maxn],ct,dep[maxn],fa[maxn],siz[maxn],tim;
ull op[maxn][];
struct N{
int to,next;
N(int t=,int n=):to(t),next(n) {}
}edge[maxn<<];
struct data{ull p0,p1;}tr[maxn<<],tl[maxn<<];
struct T{int l,r;}t[maxn<<];
void add(int x,int y){edge[++ct]=N(y,head[x]);head[x]=ct;}
void dfs1(int x,int f)
{
fa[x]=f;dep[x]=dep[f]+;siz[x]=;
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u==f)continue;
dfs1(u,x);siz[x]+=siz[u];
if(siz[u]>siz[to[x]])to[x]=u;
}
}
void dfs2(int x)
{
in[id[x]=++tim]=x;
if(to[x])tp[to[x]]=tp[x],dfs2(to[x]);
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u!=fa[x]&&u!=to[x])tp[u]=u,dfs2(u);
}
}
data update(ull op,ull w)
{
data ret;
if(op==)ret.p0=(&w),ret.p1=((~)&w);
if(op==)ret.p0=(|w),ret.p1=((~)|w);
if(op==)ret.p0=(^w),ret.p1=((~)^w);
return ret;
}
data pushup(data x,data y)
{
data ret;
ret.p0=(x.p0&y.p1) | ((~x.p0)&y.p0);
ret.p1=(x.p1&y.p1) | ((~x.p1)&y.p0);
return ret;
}
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r)
{
tl[x]=tr[x]=update(op[in[l]][],op[in[l]][]);//in[l]而非x!
return;
}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
tl[x]=pushup(tl[x<<],tl[x<<|]);
// tr[x]=pushup(tr[x<<1],tr[x<<1|1]);
tr[x]=pushup(tr[x<<|],tr[x<<]);//!!!!!!!!!! }
data sch(int x,int l,int r,int fl)
{
if(t[x].l>=l&&t[x].r<=r)
return fl?tr[x]:tl[x];
// int mid=((l+r)>>1);
int mid=((t[x].l+t[x].r)>>);
if(r<=mid)return sch(x<<,l,r,fl);
else if(l>mid)return sch(x<<|,l,r,fl);
else return pushup(sch((x<<)+fl,l,r,fl),sch((x<<|)-fl,l,r,fl));//从左往右或从右往左pushup有不同
}
data find(int x,int y)
{
data ans1=update(,),ans2=update(,);//ans1为x到lca,ans2为y到lca
while(tp[x]!=tp[y])
{
// if(dep[x]>dep[y])
if(dep[tp[x]]>dep[tp[y]])
{
ans1=pushup(ans1,sch(,id[tp[x]],id[x],));
x=fa[tp[x]];
}
else
{
ans2=pushup(sch(,id[tp[y]],id[y],),ans2);
y=fa[tp[y]];
}
}
if(dep[x]<dep[y])return pushup(pushup(ans1,sch(,id[x],id[y],)),ans2);
else return pushup(pushup(ans1,sch(,id[y],id[x],)),ans2);
}
void query(int x,int y,ull z)//ull
{
data ans=find(x,y);ull s=,ret=;
for(int i=p-;i>=;i--)
{
if((1ull<<i)&ans.p0)ret+=(1ull<<i);
else if(((1ull<<i)&ans.p1)&&s+(1ull<<i)<=z)
ret+=(1ull<<i),s+=(1ull<<i);
}
printf("%llu\n",ret);
}
void modify(int x,int p,ull op,ull w)//ull
{
if(t[x].l==t[x].r)
{
tl[x]=tr[x]=update(op,w);
return;//
}
int mid=((t[x].l+t[x].r)>>);
if(p<=mid)modify(x<<,p,op,w);
else modify(x<<|,p,op,w);
tl[x]=pushup(tl[x<<],tl[x<<|]);
// tr[x]=pushup(tr[x<<1],tr[x<<1|1]);
tr[x]=pushup(tr[x<<|],tr[x<<]);
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=;i<=n;i++)scanf("%llu%llu",&op[i][],&op[i][]);
for(int i=,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs1(,);tp[]=;dfs2();build(,,n);
for(int i=,q,x,y;i<=m;i++)
{
ull z;//
scanf("%d%d%d%llu",&q,&x,&y,&z);
if(q==)query(x,y,z);
else modify(,id[x],y,z);//
}
return ;
}

bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+位运算的更多相关文章

  1. BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分

    原文链接http://www.cnblogs.com/zhouzhendong/p/8085286.html 题目传送门 - BZOJ4811 题意概括 是BZOJ3668长在树上并加上修改和区间询问 ...

  2. [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)

    起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...

  3. Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心

    传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...

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

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4811 题解 我现在为什么都写一题,调一天啊,马上真的退役不花一分钱了. 考虑这道题的弱化版 N ...

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

    题解: 好像和noi那题并没有什么区别 只是加上了修改和变成树上 比较显然我们可以用树链剖分来维护

  6. 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心

    Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...

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

    [BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...

  8. [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]

    题面 BZOJ题面,比较不清晰 Luogu题面,写的比较清楚 思路 原题目 我们先看这道题的原题目NOI2014起床困难综合症 的确就是上树的带修改版本 那么我们先来解决这个原版的序列上单次询问 二进 ...

  9. BZOJ4811 [Ynoi2017]由乃的OJ

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. K/3Cloud二次开发基于WebDev附加进程调试

    大部分人在进行K/3cloud二次开发插件的调试时,选择的是附加IIS进程w3wp调试,本文给大家介绍一下基于WebDev附加进程调试,不用重启iis. 步骤如下: 1)拷贝K/3cloud产品安装目 ...

  2. 《TCP/IP详解卷1:协议》——第5章 RARP:逆地址解析协议(转载)

    1.引言 具有本地磁盘的系统引导时,一般是从磁盘上的配置文件中读取IP地址.但是无盘机,如X终端或无盘工作站,则需要采用其他方法来获得IP地址. 网络上的每个系统都具有唯一的硬件地址,它是由网络接口生 ...

  3. php 翻转字符串

    //方法一 function strrev_charset($string,$charset='utf-8'){ if(!is_string($string) || !mb_check_encodin ...

  4. [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树

    游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...

  5. Sudoku Killer--hdu1426(数独 跟上一题差不多 但是输入时问题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1426 注意输入问题就行 还是dfs #include<stdio.h> #include<st ...

  6. 洛谷——P2068 统计和

    P2068 统计和 题目描述 给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=1000 ...

  7. NOIP2017 酱油记

    Day0: 怀着激动无比的小心情,坐上了学校的校车. 然后司机在某个小县城迷路了,迷路了两个多小时.... 来到酒店,去吃了几把鸡,没见到鸡屁股... 洗了个澡早早睡了.. Day1: 一早被闹铃叫醒 ...

  8. 简单使用SOCKET,TCP,UDP模式之间的通信

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中, ...

  9. Ubuntu 16.04安装Fiddler抓包工具(基于Mono,且会有BUG)

    说明:Fiddler官方提供了Mono版本的,但是只有2014版本的,不是最新的,并且运行期间会有BUG,比如界面错乱卡死等等,但是勉强能代理,抓SSL的包,如果使用了要做好心理准备.将就一下还是可以 ...

  10. jmeter的jmx脚本结构解析

    jmeter的jmx脚本是xml文档,简单分析下其结构 xml是树形结构:jmeter界面的树形结构就是xml的结构 一级目录: 二级目录:在一级目录右键后可以看到的,都可以做为二级目录 三级目录.n ...