题目传送门

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

题解

我现在为什么都写一题,调一天啊,马上真的退役不花一分钱了。


考虑这道题的弱化版 NOI2014 起床困难综合证的做法。

分成每一位来考虑,如果高位可以是 \(1\) 的话,那么尽量让高位为 \(1\)。

求出当前位为 \(0/1\) 时,最终得到的是 \(0\) 还是 \(1\)。因为要保证选的数小于 \(z\),所以对于都可以得到 \(1\) 的情况,尽量选择 \(0\) 可以解除限制。

如果 \(z\) 这一位为 \(0\) 并且现在仍然被限制着,那么显然只能取 \(0\) 了。


到了树上,考虑用树链剖分维护线段树区间合并,可以得出我们刚刚需要的东西 —— 当前位为 \(0/1\) 时,最终得到的是 \(0\) 还是 \(1\)。

但是这样做是 \(O(mk\log^2n)\) 的,无法通过 dllxl 的数据。

考虑如何优化。


可以发现其实每一位是可以压在一起来同时操作的,所以用一个 \(64\) 位的二进制数来整体地表示这个区间的结果。

也就是 \(s_0\) 表示初值为 \(0\) 的结果,\(s_1\) 表示初值为 \(111111..111\) 的结果。

这样做就可以去掉一个 \(k\) 了,时间复杂度 \(O(m(k+\log^2n))\)。


  1. #include<bits/stdc++.h>
  2. #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
  3. #define dbg(...) fprintf(stderr, __VA_ARGS__)
  4. #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
  5. #define fi first
  6. #define se second
  7. #define pb push_back
  8. template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
  9. template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
  10. typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
  11. template<typename I>
  12. inline void read(I &x) {
  13. int f = 0, c;
  14. while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
  15. x = c & 15;
  16. while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
  17. f ? x = -x : 0;
  18. }
  19. #define lc o << 1
  20. #define rc o << 1 | 1
  21. const int N = 100000 + 7;
  22. int n, m, k, dfc;
  23. ull S;
  24. int opt[N];
  25. ull v[N];
  26. int dep[N], f[N], siz[N], son[N], dfn[N], pre[N], top[N];
  27. struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
  28. inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
  29. inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }
  30. struct Node {
  31. ull s[2], r[2];
  32. inline Node() : s{0, S}, r{0, S} {}
  33. inline Node(const int &i) {
  34. int opt = ::opt[i];
  35. ull v = ::v[i];
  36. if (opt == 1) s[0] = 0, s[1] = v;
  37. else if (opt == 2) s[0] = v, s[1] = S;
  38. else s[0] = v, s[1] = (~v) & S;
  39. r[0] = s[0], r[1] = s[1];
  40. }
  41. inline Node(const ull &x, const ull &y) : s{x, y}, r{x, y} {}
  42. } t[N << 2];
  43. inline Node operator + (const Node &a, const Node &b) {
  44. Node ans;
  45. ans.s[0] = (a.s[0] & b.s[1]) | ((~a.s[0]) & b.s[0]);
  46. ans.s[1] = (a.s[1] & b.s[1]) | ((~a.s[1]) & b.s[0]);
  47. ans.r[0] = (b.r[0] & a.r[1]) | ((~b.r[0]) & a.r[0]);
  48. ans.r[1] = (b.r[1] & a.r[1]) | ((~b.r[1]) & a.r[0]);
  49. // dbg("******* %llu, %llu; %llu, %llu; %llu, %llu\n", a.s[0], a.s[1], b.s[0], b.s[1], ans.s[0], ans.s[1]);
  50. return ans;
  51. }
  52. inline Node operator - (const Node &a) {
  53. Node ans;
  54. ans.s[0] = a.r[0], ans.s[1] = a.r[1];
  55. ans.r[0] = a.s[0], ans.r[1] = a.s[1];
  56. return ans;
  57. }
  58. inline void build(int o, int L, int R) {
  59. if (L == R) return t[o] = Node(pre[L]), (void)0;
  60. int M = (L + R) >> 1;
  61. build(lc, L, M), build(rc, M + 1, R);
  62. t[o] = t[lc] + t[rc];
  63. }
  64. inline void qadd(int o, int L, int R, int x) {
  65. if (L == R) return t[o] = Node(pre[L]), (void)0;
  66. int M = (L + R) >> 1;
  67. if (x <= M) qadd(lc, L, M, x);
  68. else qadd(rc, M + 1, R, x);
  69. t[o] = t[lc] + t[rc];
  70. }
  71. inline Node qsum(int o, int L, int R, int l, int r) {
  72. if (l <= L && R <= r) return t[o];
  73. int M = (L + R) >> 1;
  74. if (r <= M) return qsum(lc, L, M, l, r);
  75. if (l > M) return qsum(rc, M + 1, R, l, r);
  76. return qsum(lc, L, M, l, r) + qsum(rc, M + 1, R, l, r);
  77. }
  78. inline Node qry(int x, int y) {
  79. Node ans1, ans2;
  80. while (top[x] != top[y]) {
  81. if (dep[top[x]] > dep[top[y]]) {
  82. ans1 = qsum(1, 1, n, dfn[top[x]], dfn[x]) + ans1;
  83. x = f[top[x]];
  84. } else {
  85. ans2 = qsum(1, 1, n, dfn[top[y]], dfn[y]) + ans2;
  86. y = f[top[y]];
  87. }
  88. }
  89. // dbg("x = %d, y = %d, dfn: %d %d\n", x, y, dfn[x], dfn[y]);
  90. if (dep[x] < dep[y]) ans2 = qsum(1, 1, n, dfn[x], dfn[y]) + ans2;
  91. else ans1 = qsum(1, 1, n, dfn[y], dfn[x]) + ans1;
  92. ans1 = (-ans1) + ans2;
  93. return ans1;
  94. }
  95. inline ull solve(int x, int y, ull z) {
  96. Node a = qry(x, y);
  97. // dbg("a.s[0] = %llu, a.s[1] = %llu, S = %llu, **** %llu\n", a.s[0], a.s[1], S, 9571068480616515248ull | 16544127868907869972ull);
  98. // dbg("*** a.s[0] = %llu, a.s[1] = %llu\n", (qry(2, 2)).s[0], (qry(2, 2)).s[1]);
  99. ull ans = 0, lim = 1;
  100. for (int i = k - 1; ~i; --i) {
  101. // dbg("%llu, %llu %llu\n", (z >> i) & 1, ((a.s[0] >> i) & 1), ((a.s[1] >> i) & 1));
  102. if ((!lim || ((z >> i) & 1)) && !((a.s[0] >> i) & 1) && ((a.s[1] >> i) & 1)) ans |= 1ull << i;
  103. else ans |= (1ull << i) & a.s[0], lim = lim && !((z >> i) & 1);//, dbg("i = %d\n", i);
  104. }
  105. // ull ans2 = 0;
  106. // for (int i = 0; i <= z; ++i) {
  107. // ull cnt = 0;
  108. // for (int j = k - 1; ~j; --j) cnt += a.s[(i >> j) & 1] & (1ull << j);
  109. // smax(ans2, cnt);
  110. // }
  111. return ans;
  112. }
  113. inline void dfs1(int x, int fa = 0) {
  114. dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
  115. for fec(i, x, y) if (y != fa) dfs1(y, x), siz[x] += siz[y], siz[y] > siz[son[x]] && (son[x] = y);
  116. }
  117. inline void dfs2(int x, int pa) {
  118. top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
  119. if (!son[x]) return; dfs2(son[x], pa);
  120. for fec(i, x, y) if (y != f[x] && y != son[x]) dfs2(y, y);
  121. }
  122. inline void work() {
  123. dfs1(1), dfs2(1, 1), build(1, 1, n);
  124. while (m--) {
  125. int opt, x, y;
  126. ull z;
  127. read(opt), read(x), read(y), read(z);
  128. if (opt == 2) ::opt[x] = y, v[x] = z, qadd(1, 1, n, dfn[x]);
  129. else printf("%llu\n", solve(x, y, z));
  130. }
  131. }
  132. inline void init() {
  133. read(n), read(m), read(k);
  134. if (k < 64) S = (1ull << k) - 1;
  135. else S = -1;
  136. // dbg("k = %d, S = %llu, %llu\n", k, (1ull << (k - 0)), 1ull << 64);
  137. for (int i = 1; i <= n; ++i) read(opt[i]), read(v[i]);
  138. int x, y;
  139. for (int i = 1; i < n; ++i) read(x), read(y), adde(x, y);
  140. }
  141. int main() {
  142. #ifdef hzhkk
  143. freopen("hkk.in", "r", stdin);
  144. #endif
  145. init();
  146. work();
  147. fclose(stdin), fclose(stdout);
  148. return 0;
  149. }

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://www.lydsy.com/JudgeOnline/problem.php?id=4811 因为位运算的结果有可合并性,所以可以树链剖分,线段树维护: 细节很多,特别要注意从左往 ...

  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. EOJ - 3631 Delivery Service 2018.8华师大月赛(树链剖分+贪心)

    链接:https://acm.ecnu.edu.cn/contest/103/problem/D/ 题意:给你一棵无向边连接的树,边的权值可以任意互换.有m次运输,每次的花费是点u到v路径上边的权值和 ...

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

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

随机推荐

  1. (转载)《利用Python进行数据分析·第2版》电子书

    https://www.jianshu.com/p/04d180d90a3f https://www.jianshu.com/p/04d180d90a3f https://www.jianshu.co ...

  2. 如何删除eclipse的subclipse插件记住的SVN用户名和密码

    如何删除eclipse的subclipse插件记住的SVN用户名和密码找到auth目录,将其以及子目录.子文件都删除.路径在:C:\Users\Administrator\AppData\Roamin ...

  3. 蒟蒻的splay 1---------洛谷板子题普通平衡树

    前言部分 splay是个什么东西呢? 它就是个平衡树,支持以下操作 这些操作还可以用treap,替罪羊树,红黑树,multiset balabala(好像混进去什么奇怪的东西) 这里就只说一下spla ...

  4. DAY 6 TEST

    test T1 样例输入 样例输出 答案选择u,v作为关键点 暴力的话k^2枚举跑最短路,寻找最小值就行了 50pts 考虑优化枚举量 因为答案的两个点是不同的点,所以编号的二进制表示中至少一位不同 ...

  5. Django学习之视图

    一.Django的View(视图) 1.一个简单的视图 3.CBV和FBV 4.给视图加装饰器 使用装饰器装饰FBV 使用装饰器装饰CBV 二.Request对象和Response对象 1.reque ...

  6. SpringBoot系列:三、SpringBoot中使用Filter

    在springboot中要使用Filter首先要实现Filter接口,添加@WebFilter注解 然后重写三个方法,下图示例是在Filter中过滤上一届中拿配置的接口,如果是这个接口会自动跳转到/P ...

  7. tensorflow学习笔记二:入门基础 好教程 可用

    http://www.cnblogs.com/denny402/p/5852083.html tensorflow学习笔记二:入门基础   TensorFlow用张量这种数据结构来表示所有的数据.用一 ...

  8. Net的网络层的构建(源码分析)

    概述 网络层的构建是在Net<Dtype>::Init()函数中完成的,构建的流程图如下所示: 从图中可以看出网络层的构建分为三个主要部分:解析网络文件.开始建立网络层.网络层需要参与计算 ...

  9. 字符串中的TRIM操作

    std::string& ltrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") ...

  10. python函数-基础知识

    一.含义函数是程序内的“小程序” 二.示例 #!/usr/bin/env python #coding:utf-8 def hello(): print('Hello world!') print(' ...