Portal --> bzoj4811

Solution

   这题可以用树剖+线段树做也可以用LCT做,不过大体思路是一样的

   (接下来先讲的是树剖+线段树的做法,再提LCT的做法)

​   首先位运算有一个非常优秀的性质就是写成二进制之后每位的运算是独立的

   所以我们可以巧妙利用这个性质来做这题

   我们考虑维护在二进制中每一位的\(0\)和\(1\)在从\(x\)走到\(y\)之后会变成什么,这样在查询的时候枚举每一位然后贪心就好了,“从\(x\)走到\(y\)”这个可以用树剖搞定,现在的问题是线段树中如何合并两段区间的答案(记为\(info\),这是一个结构体,\(info.x_0\)表示带\(0\)进去的答案,\(info.x_1\)表示带\(1\)进去的答案)

​   先不考虑时间和空间问题,假设我们对于每一位都种了一棵线段树,某一位的线段树种每个节点的\(info\)记录的就是将这位的\(0\)和\(1\)带进去走完\(dfn\)序为\(l\)到\(r\)的这段之后得到的结果(\(0\)或者\(1\))

   再具体一点,假设我们将所有的节点按照\(dfn\)序存在\(lis\)数组里面,那么对于第\(i\)位的线段树中的\([l,r]\)的节点,\(info.x_0\)记录的是\(0\)依次与\(lis[l]....lis[r]\)这些节点进行计算最后得到结果的第\(i\)位,\(info.x_1\)记录的是\(2^i-1\)(额就是二进制下\(i\)个1)依次与\(lis[l]...lis[r]\)这些节点进行计算最后得到的结果的第\(i\)位

​   然后因为这里位数最多是\(64\),我们完全可以用一个unsigned long long将所有的位压起来,只用一棵线段树处理,这样就时间和空间都不会有问题了

  

​   那么现在的问题就是如何用左儿子和右儿子的信息来更新当前节点(\(x\))的信息了

​   先把式子写出来:

\[info[x].x_0=(info[lch].x_0\&info[rch].x_1)|((\sim info[lch].x_0)\& info[rch].x_0)\\
info[x].x_1=(info[lch].x_1\&info[rch].x_1)|((\sim info[lch].x_1)\& info[rch].x_0)\\
\]

​   两个式子的原理差不多,这里就拿\(x_0\)的式子来解释一下:\((info[lch].x_0\&info[rch].x_1)\)这一部分算的是\(0\)经过\(lch\)的区间之后变成了\(1\),然后再经过\(rch\)之后变成\(0\)或者\(1\),\(((\sim info[lch].x_0)\& info[rch].x_0)\)这部分是\(0\)经过\(lch\)之后还是\(0\),然后经过\(rch\)再变成对应的数字

   再具体一点的话就是,对于第一部分,取完\(\&\)之后只有变成\(1\)的\(0\)那些位置被保存了下来,如果说这位在经过\(info[rch].x_1\)之后变成了\(1\)的话,\(\&\)完了还是\(1\),否则就是\(0\),也就是相当于变成了走完\(lch\)和\(rch\)之后的结果,第二部分就是把\(info[lch].x_0\)取反一下,这样\(\&\)之后保留下来的就是变成\(0\)的那些位置,然后后面的部分就和变成\(0\)一样了

​   

   然后线段树搞完了,那直接套个树剖,查询的时候枚举每一位,贪心一下就好了

​   但是!这里有一个小问题,我们注意到位运算是不满足交换律的,也就是说涉及到一个方向的问题,所以线段树中应该要维护\(dfn[l]....dfn[r]\)和\(dfn[r]....dfn[l]\)这两个方向的\(info\),查询的时候也要注意方向是往上走还是往下走,合并的话后者和前者的唯一区别就是把\(lch\)和\(rch\)的位置换了一下(仔细想想就明白了)

​   那所以这题就做完了

​  

​   这个时候我们再来看看LCT怎么做

   然后我们会发现LCT好做很多== 因为。。LCT的瓶颈在于怎么维护\(info\)。。。所以你直接splay维护两个方向的\(info\)然后把update函数改成上面的那样合并,其他都是常规操作==

​   

   但是我。。一开始走上了一条错误的道路写了线段树然后就不想改了==

   代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#define ull unsigned long long
#define Pr pair<ull,ull>
#define mp make_pair
using namespace std;
const int N=100010,SEG=N*4,TOP=63;
struct xxx{
int y,nxt;
}a[N*2];
int h[N],op[N],sz[N],son[N],pre[N],lis[N],dfn[N],top[N],dep[N];
ull pw[TOP+1],val[N];
int n,m,dfn_t,tot,K;
ull ans,One;
ull calc(int which,ull v){
if (op[which]==1) return v&val[which];
else if (op[which]==2) return v|val[which];
return v^val[which];
}
struct Data{/*{{{*/
ull x0,x1;
Data(){}
Data(ull xx0,ull xx1){x0=xx0; x1=xx1;}
friend Data merge(Data L,Data R){
Data ret;
ret.x0=(L.x0&R.x1)|((~L.x0)&(R.x0));
ret.x1=(L.x1&R.x1)|((~L.x1)&(R.x0));
return ret;
}
}rec1[N],rec2[N];/*}}}*/
namespace Seg{/*{{{*/
int ch[SEG][2];
Data info[SEG][2];//0(down: ->),1(up: <-) info[x][dir]
int tot,n;
void pushup(int x){
info[x][0]=merge(info[ch[x][0]][0],info[ch[x][1]][0]);
info[x][1]=merge(info[ch[x][1]][1],info[ch[x][0]][1]);
}
void _build(int x,int l,int r){
info[x][0]=Data(0,0); info[x][1]=info[x][0];
if (l==r){
info[x][0]=Data(calc(lis[l],0),calc(lis[l],One));
info[x][1]=info[x][0];
return;
}
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
pushup(x);
}
void build(int _n){n=_n; tot=1; _build(1,1,n);}
void _update(int x,int d,int lx,int rx){
if (lx==rx){
info[x][0]=Data(calc(lis[lx],0),calc(lis[lx],One));
info[x][1]=info[x][0];
return;
}
int mid=lx+rx>>1;
if (d<=mid) _update(ch[x][0],d,lx,mid);
else _update(ch[x][1],d,mid+1,rx);
pushup(x);
}
void update(int d){_update(1,d,1,n);}
Data _query(int x,int l,int r,int lx,int rx,int dir){
if (l<=lx&&rx<=r) return info[x][dir];
int mid=lx+rx>>1;
Data tmp;
if (r<=mid) return _query(ch[x][0],l,r,lx,mid,dir);
else if (l>mid) return _query(ch[x][1],l,r,mid+1,rx,dir);
else{
tmp=_query(ch[x][0],l,mid,lx,mid,dir);
if (dir==0) tmp=merge(tmp,_query(ch[x][1],mid+1,r,mid+1,rx,dir));
else tmp=merge(_query(ch[x][1],mid+1,r,mid+1,rx,dir),tmp);
return tmp;
}
}
Data query(int l,int r,int dir){return _query(1,l,r,1,n,dir);}
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
void dfs(int fa,int x,int d){
int u;
son[x]=0; sz[x]=1; dep[x]=d; pre[x]=fa;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa) continue;
dfs(x,u,d+1);
sz[x]+=sz[u];
if (sz[u]>sz[son[x]]) son[x]=u;
}
}
void dfs1(int fa,int x){
int u;
dfn[x]=++dfn_t; lis[dfn_t]=x;
if (son[x]){
top[son[x]]=top[x];
dfs1(x,son[x]);
}
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa||u==son[x]) continue;
top[u]=u;
dfs1(x,u);
}
}
Data Solve(int x,int y){//0:down 1:up
int cnt1=0,cnt2=0;
Data ret=Data(0,One);
while (top[x]!=top[y]){
if (dep[top[x]]>dep[top[y]]){
rec1[++cnt1]=Seg::query(dfn[top[x]],dfn[x],1);
x=pre[top[x]];
}
else{
rec2[++cnt2]=Seg::query(dfn[top[y]],dfn[y],0);
y=pre[top[y]];
}
}
if (dep[x]<dep[y])
rec2[++cnt2]=Seg::query(dfn[x],dfn[y],0);
else
rec1[++cnt1]=Seg::query(dfn[y],dfn[x],1);
for (int i=1;i<=cnt1;++i) ret=merge(ret,rec1[i]);
for (int i=cnt2;i>=1;--i) ret=merge(ret,rec2[i]);
return ret;
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y,Q;
Data tmp;
ull tmp0,tmp1,z;
scanf("%d%d%d",&n,&m,&K);
One=1;One=One<<63;One=One*2-1;
for (int i=0;i<=K;++i) pw[i]=(ull)1<<i;
for (int i=1;i<=n;++i) scanf("%d%llu",op+i,val+i);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(0,1,1);
top[1]=1;
dfs1(0,1);
Seg::build(n);
for (int i=1;i<=m;++i){
scanf("%d%d%d%llu",&Q,&x,&y,&z);
if (Q==1){
tmp=Solve(x,y);
ans=0;
for (int i=TOP;i>=0;--i){
tmp0=(tmp.x0>>i)&1;
tmp1=(tmp.x1>>i)&1;
if (tmp0>=tmp1||pw[i]>z)
ans|=(tmp0?pw[i]:0);
else
ans|=(tmp1?pw[i]:0),z-=pw[i];
}
printf("%llu\n",ans);
}
else{
op[x]=y; val[x]=z;
Seg::update(dfn[x]);
}
}
}

【bzoj4811】由乃的OJ的更多相关文章

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

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

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

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

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

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

  4. BZOJ4811 [Ynoi2017]由乃的OJ

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

  5. BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)

    先考虑NOI2014的水题,显然从高位到低位贪心,算一下该位取0和1分别得到什么即可. 加强这个水题,变成询问区间.那么线段树维护该位取0和1从左到右和从右到左走完这个节点表示的区间会变成什么即可,也 ...

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

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

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

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

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

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

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

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

随机推荐

  1. Selenium2+python自动化-文件上传

    前言 文件上传是web页面上很常见的一个功能,自动化成功中操作起来却不是那么简单. 一般分两个场景:一种是input标签,这种可以用selenium提供的send_keys()方法轻松解决:另外一种非 ...

  2. Boss直聘邮件通知小脚本

    Boss 基于Python3的找工作利器--Boss直聘来消息邮件通知, 自动发送简历脚本,O(∩_∩)O~ 无聊写的,因为有时候觉得找工作心急如焚,想自动回复自动发简历啊有木有~~~ github地 ...

  3. Focalprice李培亮:梦想让人在我店里排队

    [亿邦动力网讯]4月3日消息,外贸B2C平台Focalprice总裁李培亮日前亮相亿邦动力网联合河南省商务厅举办的“第九届中国中小企业电子商务大会暨2014中国(河南)跨境贸易电子商务峰会”,表达自己 ...

  4. js 零零散散的总结。

    Array.slice.call(arguments);可以将一个类数组转化为数组. Array.from() ,[...arr];也可以将一个类数组转化为数组(es6). (function() { ...

  5. Beta周王者荣耀交流协会第六次会议

    1.立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:袁玥 2. 时间跨度 2017年11月15日 19:00 — 19:10 ,总计10分钟. 3. 地点 一食堂 ...

  6. HDU 5651 xiaoxin juju needs help 逆元

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5651 bc:http://bestcoder.hdu.edu.cn/contests/con ...

  7. HttpCookie Class

    提供创建和操作各 HTTP Cookie 的类型安全方法. #region 写入指定Cookie的值 +static void WriteCookie(string cookieName, strin ...

  8. vsftpd:非常安全的ftp服务端程序

    主程序:/usr/sbin/vsftpd 主配置文件:/etc/vsftpd/vsftpd.conf CentOS 6  /etc/rc.d/init.d/vsftpd chkconfig vsftp ...

  9. HDU 2105 The Center of Gravity

    http://acm.hdu.edu.cn/showproblem.php?pid=2105 Problem Description Everyone know the story that how ...

  10. maven Web项目中POM的配置信息

    什么是POM? POM是项目对象模型(Project Object Model)的简称,它是Maven项目中的文件,使用XML表示,名称叫做pom.xml.在Maven中,当谈到Project的时候, ...