省队集训Day1 睡觉困难综合征
传送门:https://www.luogu.org/problem/show?pid=3613
【题解】
按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做。
写棵LCT,维护正反两种权值,每个维护2种,代表全0的输出和全1的输出。
然后直接上LCT即可。
权值的合并有点trick,可以参考代码,需要压位。
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + ;
const int mod = 1e9+; int n, m, K; struct node {
ull p0, p1;
node () {}
node (ull p0, ull p1) : p0(p0), p1(p1) {}
friend node operator + (node a, node b) {
return node( (a.p0 & b.p1) | ((~a.p0) & b.p0), (a.p1 & b.p1) | ((~a.p1) & b.p0) );
}
}; inline node deal(int op, ull x) {
if(op == ) return node(, x);
if(op == ) return node(x, ull(-));
if(op == ) return node(x, ~x);
} struct LCT {
int ch[M][], fa[M];
bool rev[M];
node w[M][], val[M];
# define ls ch[x][]
# define rs ch[x][]
inline void up(int x) {
if(!x) return ;
w[x][] = w[x][] = val[x];
if(ls) w[x][] = w[ls][] + w[x][], w[x][] = w[x][] + w[ls][];
if(rs) w[x][] = w[x][] + w[rs][], w[x][] = w[rs][] + w[x][];
}
inline void pushrev(int x) {
if(!x) return ;
rev[x] ^= ;
swap(ch[x][], ch[x][]);
swap(w[x][], w[x][]);
}
inline void down(int x) {
if(!x || !rev[x]) return ;
pushrev(ls); pushrev(rs);
rev[x] = ;
}
# undef ls
# undef rs
inline bool isrt(int x) {
return ch[fa[x]][] != x && ch[fa[x]][] != x;
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], ls = ch[y][] == x, rs = ls^;
if(!isrt(y)) ch[z][ch[z][] == y] = x;
fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
up(y); up(x);
}
int st[M];
inline void splay(int x) {
int stn = , tx = x;
while(!isrt(tx)) st[++stn] = tx, tx = fa[tx];
st[++stn] = tx;
for (int i=stn; i; --i) down(st[i]);
while(!isrt(x)) {
int y = fa[x], z = fa[y];
if(!isrt(y)) {
if((ch[z][] == y)^(ch[y][] == x)) rotate(x);
else rotate(y);
}
rotate(x);
}
} inline int access(int x) {
int t = ;
for (; x; t = x, x = fa[x]) {
splay(x);
ch[x][] = t;
up(x);
}
return t;
} inline void makeroot(int x) {
access(x); splay(x); pushrev(x);
} inline void link(int x, int y) {
makeroot(y); fa[y] = x;
}
}T; # define bit(x, i) (((x) >> (i)) & ) int main() {
// freopen("sleep.in", "r", stdin);
// freopen("sleep.out", "w", stdout);
scanf("%d%d%d", &n, &m, &K);
for (int i=, op; i<=n; ++i) {
ull x;
scanf("%d%llu", &op, &x);
T.val[i] = T.w[i][] = T.w[i][] = deal(op, x);
T.ch[i][] = T.ch[i][] = T.fa[i] = T.rev[i] = ;
}
for (int i=, u, v; i<n; ++i) {
scanf("%d%d", &u, &v);
T.link(u, v);
}
int op, x, y; ull z, tx, ty, ans, t;
while(m--) {
scanf("%d%d%d%llu", &op, &x, &y, &z);
if(op == ) {
ans = ; t = ;
T.makeroot(x); T.access(y); T.splay(y);
tx = T.w[y][].p0, ty = T.w[y][].p1;
for (int i=; ~i; --i) {
if(bit(tx, i)) ans |= (1ull << i);
else if(bit(ty, i)) {
if(t + (1ull << i) <= z) t = t + (1ull << i), ans |= (1ull << i);
}
}
printf("%llu\n", ans);
} else {
T.splay(x);
T.val[x] = deal(y, z);
T.up(x);
}
}
return ;
}
省队集训Day1 睡觉困难综合征的更多相关文章
- 【刷题】洛谷 P3613 睡觉困难综合征
题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...
- Luogu 睡觉困难综合征 ([NOI2014]起床困难综合症)
一.[NOI2014]起床困难综合症 题目描述 网址:https://daniu.luogu.org/problemnew/show/2114 大意: 有一条链,链上每一个节点包含一个位运算f 与 一 ...
- Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心
传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...
- 洛谷P3613 睡觉困难综合征(LCT,贪心)
洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...
- 洛谷P3613 睡觉困难综合征(LCT)
题目: P3613 睡觉困难综合症 解题思路: LCT,主要是维护链上的多位贪心答案,推个公式:分类讨论入0/1的情况,合并就好了(公式是合并用的) 代码(我不知道之前那个为啥一直wa,改成结构体就好 ...
- Luogu3613 睡觉困难综合征
题面描述https://www.luogu.org/problemnew/show/3613 原题NOI2014起床困难综合症https://www.luogu.org/problemnew/show ...
- P3613 睡觉困难综合征(LCT + 位运算)
题意 NOI2014 起床困难综合症 放在树上,加上单点修改与链上查询. 题解 类似于原题,我们只需要求出 \(0\) 和 \(2^{k - 1} - 1\) 走过这条链会变成什么值,就能确定每一位为 ...
- FJ省队集训DAY1 T1
题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会 ...
- [洛谷]P3613 睡觉困难综合征
题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对 ...
随机推荐
- Java版office文档在线预览
java将office文档pdf文档转换成swf文件在线预览 第一步,安装openoffice.org openoffice.org是一套sun的开源office办公套件,能在widows,linux ...
- LintCode-532.逆序对
逆序对 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.给你一个数组,求出这个数组中逆序对的总数. 概括:如果a[i] > a[j] 且 i < j, a[i ...
- idea快捷键操作
在编写代码的时候直接输入psv就会看到一个psvm的提示,此时点击tab键一个main方法就写好了. psvm 也就是public static void main的首字母. 依次还有在方法体内键入f ...
- 【Linux】- 开启远程连接
1.首先看看自己的Ubuntu是不是已经安装或启用了ssh服务,执行 ps -e |grep ssh 我们看到只有ssh-agent 这个是ssh-client客户端服务,如果有sshd,证明你已经装 ...
- matlab如何将数组中的NAN值去除
比如我们一组数据,里面有不少的NaN值,如何将其删除掉呢?可以通过find函数来搞定. 我们可以通过importdata('data.txt')将数据文件data.txt导入数组A中. ...
- Microsoft Edge goes Chromium
Microsoft Edge goes Chromium https://techcrunch.com/2018/12/06/microsoft-edge-goes-chromium-and-maco ...
- ADO.NET中DataSet、DataTable、DataRow的数据复制方法
DataSet 对象是支持 ADO.NET的断开式.分布式数据方案的核心对象 ,用途非常广泛.我们很多时候需要使用其中的数据,比如取得一个DataTable的数据或者复制另一个DataTabe中的数据 ...
- SQL SERVER 存储过程中SELECT 返回值如何赋值给变量
今天在处理一个问题时,使用到一个存储过程,是用于更新并获取最新ID的.在使用过程中,需要获取到这个ID并赋值给变量,结果用EXEC @ID = 存储过程的方式获取失败了.具体情况如下: 为了还原整个情 ...
- 使用 ECS 实例创建 FTP 站点 linux
本文只做记载过程和问题,并不详细 官方教程走一遍 https://help.aliyun.com/document_detail/51998.html#h2-linux-ftp-2 值得注意的是步骤二 ...
- 【Python】PYTHON中STRIP()方法学习笔记
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 当使用strip('xxx'),只要字符串头尾有"xxx"中的一个,就会去掉,而不是符合字符串''x ...