题意

NOI2014 起床困难综合症 放在树上,加上单点修改与链上查询。

题解

类似于原题,我们只需要求出 \(0\) 和 \(2^{k - 1} - 1\) 走过这条链会变成什么值,就能确定每一位为 \(0 / 1\) 走完后变成什么值。

我们对于 \(LCT\) 每个节点维护两个值 \(r_0,r_1\) 表示 \(0\) 和 \(2 ^ k - 1\) 从当前 \(LCT\) 维护的链底走到这个点会变成什么值。

然后我们就可以把位运算操作变成一个值放在这个点上。

合并信息的时候,可以这样写:

inline Data operator + (const Data &lhs, const Data &rhs) {
return (Data) {
(~lhs.r0 & rhs.r0) | (lhs.r0 & rhs.r1),
(~lhs.r1 & rhs.r0) | (rhs.r1 & lhs.r1)
};
}

此处 \(\sim\) 是取反,也就是所有位反转,注意此处需要用 unsigned long long 存,就没有符号位,不会进行反转。

解释前面那个地方 (~lhs.r0 & rhs.r0) 意味着最开始从 \(0\) 开始走,走完左子树后还是 \(0\) 然后继续走 得到的结果,

(lhs.r0 & rhs.r1) 就是一开始从 \(0\) 走,走完左子树后变成 \(1\) 然后继续走 得到的结果。

另外一个也是同理了,只是最开始从 \(1\) 走。

但是这样还是不够的,因为位运算是有顺序的,\(reverse\) 的时候答案就会错误,所以我们多存一个逆向的值就行了。

最后只需要像原题按位贪心就行了。

复杂度是 \(O(n + q (\log n + k))\) 的。

总结

位运算时需要对所有位进行翻转可以用 \(\sim\) ,十分方便。

\(LCT\) 维护信息如果有顺序的话,那么需要维护一个逆向操作的答案才行。

代码

具体可以看看代码实现(虽然写的有点长。。)

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define pb push_back using namespace std; typedef unsigned long long ull; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} namespace pb_ds
{
namespace io
{
const int MaxBuff = 1 << 22;
const int Output = 1 << 24;
char B[MaxBuff], *S = B, *T = B;
#define getc() ((S == T) && (T = (S = B) + fread(B, 1, MaxBuff, stdin), S == T) ? 0 : *S++)
char Out[Output], *iter = Out;
inline void flush()
{
fwrite(Out, 1, iter - Out, stdout);
iter = Out;
}
} template<class Type> inline Type read()
{
using namespace io;
register char ch; register Type ans = 0; register bool neg = 0;
while(ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? neg = 1 : ans = ch - '0';
while(ch = getc(), '0' <= ch && ch <= '9') ans = ans * 10 + ch - '0';
return neg ? -ans : ans;
} template<class Type> inline void Print(register Type x, register char ch = '\n')
{
using namespace io;
if(!x) *iter++ = '0';
else
{
if(x < 0) *iter++ = '-', x = -x;
static int s[100]; register int t = 0;
while(x) s[++t] = x % 10, x /= 10;
while(t) *iter++ = '0' + s[t--];
}
*iter++ = ch;
} } using namespace pb_ds; void File() {
#ifdef zjp_shadow
freopen ("P3613.in", "r", stdin);
freopen ("P3613.out", "w", stdout);
#endif
} const int N = 1e5 + 1e3; #define ls(o) ch[o][0]
#define rs(o) ch[o][1] struct Data {
ull r0, r1;
}; inline Data operator + (const Data &lhs, const Data &rhs) {
return (Data) {
(~lhs.r0 & rhs.r0) | (lhs.r0 & rhs.r1),
(~lhs.r1 & rhs.r0) | (rhs.r1 & lhs.r1)
};
} template<int Maxn>
struct Link_Cut_Tree { int ch[Maxn][2], fa[Maxn]; Data fo[Maxn], fr[Maxn], val[Maxn]; inline bool is_root(int o) {
return ls(fa[o]) != o && rs(fa[o]) != o;
} inline bool get(int o) {
return rs(fa[o]) == o;
} inline void push_up(int o) {
fo[o] = fr[o] = val[o];
if (ls(o)) fo[o] = fo[ls(o)] + fo[o], fr[o] = fr[o] + fr[ls(o)];
if (rs(o)) fo[o] = fo[o] + fo[rs(o)], fr[o] = fr[rs(o)] + fr[o];
} inline void rotate(int v) {
int u = fa[v], t = fa[u], d = get(v);
fa[ch[u][d] = ch[v][d ^ 1]] = u;
fa[v] = t; if (!is_root(u)) ch[t][rs(t) == u] = v;
fa[ch[v][d ^ 1] = u] = v;
push_up(v); push_up(u);
} bool rev[Maxn]; inline void Get_Rev(int o) {
rev[o] ^= 1;
swap(ls(o), rs(o));
swap(fo[o], fr[o]);
} inline void push_down(int o) {
if (rev[o])
Get_Rev(ls(o)), Get_Rev(rs(o)), rev[o] = false;
} void Push_All(int o) {
if (!is_root(o)) Push_All(fa[o]); push_down(o);
} inline void Splay(int o) {
Push_All(o);
for (; !is_root(o); rotate(o))
if (!is_root(fa[o])) rotate(get(o) != get(fa[o]) ? o : fa[o]);
push_up(o);
} inline void Access(int o) {
for (int t = 0; o; o = fa[t = o])
Splay(o), rs(o) = t, push_up(o);
} inline void Make_Root(int o) {
Access(o); Splay(o); Get_Rev(o);
} inline void Split(int u, int v) {
Make_Root(u); Access(v); Splay(v);
} }; Link_Cut_Tree<N> T; vector<int> G[N];
void Build(int u = 1, int fa = 0) {
T.fa[u] = fa; for (int v : G[u]) if (v != fa) Build(v, u);
} int main () { File(); int n = read<int>(), m = read<int>(), k = read<int>(); For (i, 1, n) {
int x = i, y = read<int>(); ull z = read<ull>();
if (y == 1) T.val[x].r0 = 0ull, T.val[x].r1 = z;
if (y == 2) T.val[x].r0 = z, T.val[x].r1 = ~0ull;
if (y == 3) T.val[x].r0 = z, T.val[x].r1 = ~z;
T.push_up(x);
} For (i, 1, n - 1) { int u = read<int>(), v = read<int>(); G[u].pb(v); G[v].pb(u); } Build(); For (i, 1, m) {
int opt = read<int>(), x = read<int>(), y = read<int>(); ull z = read<ull>();
if (opt == 1) {
T.Split(x, y);
ull val0 = T.fo[y].r0, val1 = T.fo[y].r1, res = 0, cur = 0;
for (ull i = 1ull << (k - 1); i; i >>= 1) {
if ((val0 & i) < (val1 & i) && cur + i <= z)
cur += i, res += val1 & i;
else res += val0 & i;
}
Print(res);
} else {
T.Access(x); T.Splay(x);
if (y == 1) T.val[x].r0 = 0ull, T.val[x].r1 = z;
if (y == 2) T.val[x].r0 = z, T.val[x].r1 = ~0ull;
if (y == 3) T.val[x].r0 = z, T.val[x].r1 = ~z;
T.push_up(x);
}
}
io :: flush(); return 0; }

P3613 睡觉困难综合征(LCT + 位运算)的更多相关文章

  1. P3613 睡觉困难综合征 LCT+贪心+位运算

    \(\color{#0066ff}{ 题目描述 }\) 由乃这个问题越想越迷糊,已经达到了废寝忘食的地步.结果她发现--晚上睡不着了!只能把自己的一个神经元(我们可以抽象成一个树形结构)拿出来,交给D ...

  2. 洛谷P3613 睡觉困难综合征(LCT)

    题目: P3613 睡觉困难综合症 解题思路: LCT,主要是维护链上的多位贪心答案,推个公式:分类讨论入0/1的情况,合并就好了(公式是合并用的) 代码(我不知道之前那个为啥一直wa,改成结构体就好 ...

  3. 【刷题】洛谷 P3613 睡觉困难综合征

    题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...

  4. 洛谷P3613 睡觉困难综合征(LCT,贪心)

    洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...

  5. [洛谷]P3613 睡觉困难综合征

    题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对 ...

  6. 洛谷P3613 睡觉困难综合征

    传送门 题解 人生第一道由乃…… 做这题之前应该先去把这一题给切掉->这里 我的题解->这里 然后先膜一波zsy大佬和flashhu大佬 大体思路就是先吧全0和全1的都跑答案,然后按位贪心 ...

  7. 【Luogu】2114起床困难综合征(位运算贪心)

    题目链接 这题真是恶心死我了. 由于位运算每一位互不干涉,所以贪心由大到小选择每一位最优的解,但是要判断一下边界,如果选择该解使得原数>m则不能选择. 代码如下 #include<cstd ...

  8. NOI2014 洛谷P2114 起床困难综合征(位运算)

    呃...这道题算是noi中比较简单的题吧...... 众所周知,位运算是个好东西,它就是对应的位进行运算,跟其他的位没有关系. 我们要选取一个m值使最后的攻击力最大,对于这个m,从高位开始枚举,判断该 ...

  9. [P3613]睡觉困难综合征

    Description: 给定一个n个点的树,每个点有一个操作符号 "&" "|" "^" ,以及一个权值 要求支持以下操作: 1. ...

随机推荐

  1. pycharm设置pytest运行程序

  2. Java 基本数据类型 及 == 与 equals 方法的区别

    Java数据类型分为基本数据类型与引用数据类型. 1 基本数据类型 byte:Java中最小的数据类型,在内存中占1个字节(8 bit),取值范围-128~127,默认值0 short:短整型,2个字 ...

  3. python读文件指定行的数据

    import linecacheprint linecache.getline('url.txt',2) 读取url.txt文件的第2行内容

  4. mvn clean deploy

    如果是 mthrift的话,需要部署,就用 mvn clean deploy; 先进入  cd qcs.appeal.client ,然后执行:mvn clean deploy;

  5. 五、core开发

    一.支付方面的 https://www.cnblogs.com/stulzq/p/7606164.htmlhttps://www.cnblogs.com/guolianyu/

  6. Python——Radiobutton,Checkbutton参数说明

    anchor  : 文本位置: background(bg) : 背景色: foreground(fg) :前景色: borderwidth :  边框宽度: width   : 组件的宽度: hei ...

  7. 注解方式过滤器(Filter)不能过滤Servlet的问题

    https://www.aliyun.com/jiaocheng/778495.html 今天写filter(过滤器)的时候,碰到一个奇怪的问题,发现filter可以过滤urlPatterns,但是无 ...

  8. SQL Server中获取指定时间段内的所有月份

    例如查询 2012-1-5 到 2012-11-3 之间所有的月份 declare @begin datetime,@end datetime set @begin='2012-1-5' set @e ...

  9. 将数组Arrays转成集合List

    String[] split = pids.split("-"); //将数组split转成集合 List<String> asList = Arrays.asList ...

  10. JavaScript Decorators 的简单理解

    Decorators,装饰器的意思, 所谓装饰就是对一个物件进行美化,让它变得更漂亮.最直观的例子就是房屋装修.你买了一套房子,但是毛坯房,你肯定不想住,那就对它装饰一下,床,桌子,电视,冰箱等一通买 ...