luogu 5354 [Ynoi2017]由乃的OJ LCT+位运算
如果做过起床困难综合征的话应该很快就能有思路,没做过那道题的话还真是挺费劲的.
我们不知道要带入的值是什么,但是我们可以知道假设带入值得当前位为 $1$ 时这一位在经过位运算后是否为 $1$.
至于这个怎么维护,我们开两个变量 $f0,f1$ 代表初始带入全 $0$,全 $1$ 时每一位得值.
然后在 $LCT$ 中维护从左向右,从右向左两个方向上得这个东西,注意一下 $pushup$ 函数得写法.
这段代码十分优美,利用了按位取反等骚操作:
- struct node
- {
- ll f0,f1;
- node operator+(const node &b) const
- {
- node a;
- a.f0=(~f0&b.f0)|(f0&b.f1);
- a.f1=(~f1&b.f0)|(f1&b.f1);
- return a;
- }
- }f[N],L[N],R[N];
code:
- #include <bits/stdc++.h>
- #define N 100007
- #define ll unsigned long long
- #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
- using namespace std;
- int n,m,k,edges;
- int hd[N],to[N<<1],nex[N<<1];
- void addedge(int u,int v)
- {
- nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
- }
- struct node
- {
- ll f0,f1;
- node operator+(const node &b) const
- {
- node a;
- a.f0=(~f0&b.f0)|(f0&b.f1);
- a.f1=(~f1&b.f0)|(f1&b.f1);
- return a;
- }
- }f[N],L[N],R[N];
- struct Link_Cut_Tree
- {
- #define lson p[x].ch[0]
- #define rson p[x].ch[1]
- int sta[N];
- struct Node
- {
- int ch[2],f,rev;
- }p[N];
- int get(int x)
- {
- return p[p[x].f].ch[1]==x;
- }
- int isrt(int x)
- {
- return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x);
- }
- void pushup(int x)
- {
- L[x]=R[x]=f[x];
- if(lson) L[x]=L[lson]+L[x], R[x]=R[x]+R[lson];
- if(rson) L[x]=L[x]+L[rson], R[x]=R[rson]+R[x];
- }
- void rotate(int x)
- {
- int old=p[x].f,fold=p[old].f,which=get(x);
- if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;
- p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old;
- p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold;
- pushup(old),pushup(x);
- }
- void mark(int x)
- {
- if(!x) return;
- swap(lson,rson), swap(L[x],R[x]),p[x].rev^=1;
- }
- void pushdown(int x)
- {
- if(p[x].rev)
- {
- p[x].rev=0;
- if(lson) mark(lson);
- if(rson) mark(rson);
- }
- }
- void splay(int x)
- {
- int u=x,v=0,fa;
- for(sta[++v]=u;!isrt(u);u=p[u].f) sta[++v]=p[u].f;
- for(;v;--v) pushdown(sta[v]);
- for(u=p[u].f;(fa=p[x].f)!=u;rotate(x))
- if(p[fa].f!=u)
- rotate(get(fa)==get(x)?fa:x);
- }
- void Access(int x)
- {
- for(int y=0;x;y=x,x=p[x].f)
- {
- splay(x);
- rson=y;
- pushup(x);
- }
- }
- void makeroot(int x)
- {
- Access(x),splay(x),mark(x);
- }
- void split(int x,int y)
- {
- makeroot(x), Access(y), splay(y);
- }
- void link(int x,int y)
- {
- makeroot(x), p[x].f=y;
- }
- void cut(int x,int y)
- {
- makeroot(x),Access(y),splay(y);
- p[y].ch[0]=p[x].f=0;
- pushup(y);
- }
- #undef lson
- #undef rson
- }lct;
- void solve(int x,int y,ll z)
- {
- lct.split(x,y);
- int i;
- ll re=0;
- for(i=k-1;i>=0;--i)
- {
- if(L[y].f0&(1ll<<i)) re+=(1ll<<i);
- else if((L[y].f1&(1ll<<i)) && (1ll<<i)<=z) re+=(1ll<<i), z-=(1ll<<i);
- }
- printf("%llu\n",re);
- }
- void dfs(int u,int ff)
- {
- lct.p[u].f=ff;
- for(int i=hd[u];i;i=nex[i])
- if(to[i]!=ff) dfs(to[i],u);
- }
- int main()
- {
- int i,j;
- // setIO("input");
- scanf("%d%d%d",&n,&m,&k);
- for(i=1;i<=n;++i)
- {
- int op;
- ll y;
- scanf("%d%llu",&op,&y);
- if(op==1) f[i]=(node){0ll,y};
- if(op==2) f[i]=(node){y,~0ll};
- if(op==3) f[i]=(node){y,~y};
- lct.pushup(i);
- }
- for(i=1;i<n;++i)
- {
- int u,v;
- scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
- }
- dfs(1,0);
- for(i=1;i<=m;++i)
- {
- int op;
- scanf("%d",&op);
- if(op==1)
- {
- int x,y;
- ll z;
- scanf("%d%d%llu",&x,&y,&z);
- solve(x,y,z);
- }
- else
- {
- int x,y;
- ll z;
- scanf("%d%d%llu",&x,&y,&z);
- lct.Access(x);
- lct.splay(x);
- if(y==1) f[x]=(node){0ll,z};
- if(y==2) f[x]=(node){z,~0ll};
- if(y==3) f[x]=(node){z,~z};
- lct.pushup(x);
- }
- }
- return 0;
- }
luogu 5354 [Ynoi2017]由乃的OJ LCT+位运算的更多相关文章
- Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算)
Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算) Description T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放 ...
- P3613 睡觉困难综合征(LCT + 位运算)
题意 NOI2014 起床困难综合症 放在树上,加上单点修改与链上查询. 题解 类似于原题,我们只需要求出 \(0\) 和 \(2^{k - 1} - 1\) 走过这条链会变成什么值,就能确定每一位为 ...
- Luogu P5354 [Ynoi2017]由乃的OJ
题目 这题以前叫睡觉困难综合征. 首先我们需要知道起床困难综合征怎么做. 大概就是先用一个全\(0\)和全\(1\)的变量跑一遍处理出每一位\(1\)和\(0\)最后会变成什么. 然后高位贪心:如果当 ...
- Luogu P2114[NOI2014]起床困难综合症 【贪心/位运算】By cellur925
题目传送门 所以NOI的题现在简单惹? 30分做法:枚举开始的权值,n²过掉. 100分做法:竟然是贪心qwq.因为我们的计算背景是二进制下,所以我们贪心地想让每一位都是1.我们现在需要解决的问题,就 ...
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心
Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...
- 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树
[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...
- [Ynoi2017]由乃的OJ
题意 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号 排名.由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由 ...
- P3613 睡觉困难综合征 LCT+贪心+位运算
\(\color{#0066ff}{ 题目描述 }\) 由乃这个问题越想越迷糊,已经达到了废寝忘食的地步.结果她发现--晚上睡不着了!只能把自己的一个神经元(我们可以抽象成一个树形结构)拿出来,交给D ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
随机推荐
- 1263: 你会做蛋糕吗?(Java)
WUSTOJ 1263: 你会做蛋糕吗? 参考博客 Mitsuha_的博客 Description BobLee是个大吃货,喜欢吃好吃的,也喜欢做好吃的.比如做正方形的蛋糕.比如下图这个5*5的蛋糕. ...
- 1204: 移位运算(C)
一.题目 http://acm.wust.edu.cn/problem.php?id=1204&soj=0 二.分析 无符号短整数关键字为:unsigned short: 无符号短整数长为2字 ...
- package.json 版本解释
指定版本:比如1.2.2,遵循“大版本.次要版本.小版本”的格式规定,安装时只安装指定版本.波浪号(tilde)+ 指定版本:比如~1.2.2,表示安装1.2.x的最新版本(不低于1.2.2),但是不 ...
- c++学习总结(一)------类结构学习
基类的构造函数并没有被派生类继承 析构函数和拷贝赋值操作符同样也没有 类的设计者通过把成员函数声明为 const 以表明它们不修改类对象 把一个修改类数据成员的函数声明为 const 是非法的 (51 ...
- idea jetty:run 启动
1.首先pom 文件 <!-- jetty插件 --> <plugin> <groupId>org.mortbay.jetty</groupId> ...
- (五)Activiti之查看最新版本的流程定义
一.查看最新版本的流程定义 因为每个流程定义都可能会有好几个版本,所以有时候我们有这样的需求,查询出最新版本的流程定义的集合 第一步:我们通过Activiti接口来获取根据流程定义Version升序排 ...
- (二)Struts.xml文件详解
一.Struts.xml文件 Struts.xml文件构成 如图,<Struts>标签内共有5个子标签. 1.1 struts-default.xml 查看Struts的内容可知,Stru ...
- 中国5级行政区域MySQL数据库库
爬取国家统计局官网的行政区域数据,包括省市县镇村5个层级,其中港澳地区的数据只有3级;台湾地区4级;包含大陆地区的邮政编码和经纬度信息. 行政划分的总体结构是: 省->市(州)->县(区) ...
- vue 集成 NEditor 富文本
下载NEditor 放在 vue 项目下面 public 文件中. 安装 vue-neditor-wrap 执行命令 npm install vue-neditor-wrap 代码使用 ...
- Android 主Module引用依赖Module,却无法使用里面的依赖库
如果模块化开发中遇到 多模块的AndroidManifest.xml没有合并or多模块的资源文件没有合并or模块A include了模块B,而无法使用模块B内依赖的其他aar包中的类的时候or提示Su ...