樱桃莓莓

题目链接:YBT2023寒假Day4 C

题目大意

有一个黑盒操作满足交换律和结合律,有 n 个数,q 次询问,每次选 m 个下标,你要计算所有不包含那 m 个下标的数进行黑盒操作之后的结果。
预处理不超过 4n 次,每次询问不超过 4(m+1) 次。(这里的一次是指使用一次黑盒操作)

思路

第一步想到的应该是前缀后缀,但是中间的要怎么办呢。
考虑分块(有点四毛子的感觉),求出每一块的前缀后缀。
但是发现怎么都还是会超 4 n 4n 4n,那这个时候考虑不要了整个的前缀后缀,思考超 4 n 4n 4n 的原因。

就是一个块 [ x , y ] [x,y] [x,y] 内如果 [ x + 1 , y − 1 ] [x+1,y-1] [x+1,y−1] 问这个就寄了。
(块长小的话要拼的也太多了)
那考虑每个块中间你在弄一个点,从这个点往前和往后在处理一遍。
(那现在是 3 n 3n 3n)

先看看够不够,发现当 B = 8 B=8 B=8 的时候,如果小块的询问没有跨越中间的部分,那它长度至多是 4 4 4,我们就可以暴力一个一个点并起来查询。
那小块就可以了,接着搞大块,考虑怎么办。

试着能不能用线段树的结构,会发现好像如果要这样的话,你合并的时候时间又超了。
考虑分摊一下,分摊到预处理那里,于是考虑线段树每个位置你都处理一个前缀后缀。
然后到询问第一次裂成两半的时候,你就可以直接分别用那两半的后缀和前缀直接拼出来。

于是数一数行不行。
如果整个询问是小块,至多是 4 4 4 可以。
如果询问分成两个小块和大段,每个小块由于分出来的一定是前缀或者后缀,大段我们用线段树的的方法至多 2 2 2 次,也是 4 4 4。
然后看初始化,前面的是 3 n 3n 3n,考虑给线段树那个部分是多少。
注意线段树是把段分线段树的,所以总的是 2 n / 8 log ⁡ n / 8 2n/8\log n/8 2n/8logn/8,会发现超了。

不过其实这个 2 2 2 可以去掉,因为一个线段树上的点要么是只用前缀,要么是只用后缀(根据它下标的奇偶, 1 1 1 就不会有)
所以就是 n / 8 log ⁡ n / 8 n/8\log n/8 n/8logn/8,大概是 1901 1901 1901 左右当 n = 2000 n=2000 n=2000,就 < n <n <n,所以是可以的。

代码

#include <algorithm>
#include <vector>
#include <cstdio>
#include <set>
#include "blackbox.h"
#define ull unsigned long longusing namespace std;const int N = 10000;
int n, m, B = 8, blo[N], bl[N], br[N];
ull pre[N], suf[N], Mid[N], b[N];struct XD_tree {ull f[N][N];void build(int now, int l, int r) {if (now != 1) {if (now & 1) {f[now][l] = pre[br[l]];for (int j = l + 1; j <= r; j++) f[now][j] = magic(f[now][j - 1], pre[br[j]]);} else {f[now][r] = pre[br[r]];for (int j = r - 1; j >= l; j--) f[now][j] = magic(f[now][j + 1], pre[br[j]]);}}if (l == r) return;int mid = (l + r) >> 1;build(now << 1, l, mid);build(now << 1 | 1, mid + 1, r);}ull query(int now, int l, int r, int L, int R) {if (L <= l && r <= R) {if (now & 1) return f[now][r];else return f[now][l];}int mid = (l + r) >> 1;if (L <= mid && mid < R) return magic(f[now << 1][L], f[now << 1 | 1][R]);if (L <= mid) return query(now << 1, l, mid, L, R);if (mid < R) return query(now << 1 | 1, mid + 1, r, L, R);}
}T;void init(vector <ull> a, int M) {n = a.size(); m = M;for (int i = 1; i <= n; i++) b[i] = a[i - 1], blo[i] = (i - 1) / B + 1;for (int i = 1; i <= blo[n]; i++) {bl[i] = (i - 1) * B + 1; br[i] = min(n, i * B); int l = bl[i], r = br[i];pre[l] = b[l]; for (int j = l + 1; j <= r; j++) pre[j] = magic(pre[j - 1], b[j]);suf[r] = b[r]; for (int j = r - 1; j >= l; j--) suf[j] = magic(suf[j + 1], b[j]);int mid = min(n, l + 3);Mid[mid] = b[mid]; for (int j = mid - 1; j >= l; j--) Mid[j] = magic(Mid[j + 1], b[j]);if (mid != r) {Mid[mid + 1] = b[mid + 1]; for (int j = mid + 2; j <= r; j++) Mid[j] = magic(Mid[j - 1], b[j]);}}T.build(1, 1, blo[n]);
}ull slove(int l, int r) {if (blo[l] == blo[r]) {int mid = blo[l] + 3;if (r - l + 1 > 4) return magic(Mid[l], Mid[r]);ull re = b[l];for (int i = l + 1; i <= r; i++) re = magic(re, b[i]);return re;}ull re = magic(suf[l], pre[r]);if (blo[l] != blo[r] - 1) re = magic(re, T.query(1, 1, blo[n], blo[l] + 1, blo[r] - 1));return re;
}ull query(vector <int> u) {sort(u.begin(), u.end());ull ans = 0;int las = 0, nof = 0;for (int i = 0; i < m; i++) {int l = las + 1, r = u[i];if (l <= r) {if (!nof) nof = 1, ans = slove(l, r);else ans = magic(ans, slove(l, r));}las = u[i] + 1;}if (las != n) {if (!nof) ans = slove(las + 1, n);else ans = magic(ans, slove(las + 1, n));}return ans;
}

【YBT2023寒假Day4 C】樱桃莓莓(交互)(四毛子分块)(线段树)相关推荐

  1. 【YBT2023寒假Day3 C】樱桃莓莓(凸包)(线段树)

    樱桃莓莓 题目链接:YBT2023寒假Day3 C 题目大意 给你一棵有根数,点有 a,b 两种权值. 然后一个点的分数是它以及它所有祖先的 a 权值和的绝对值乘上 b 权值和的绝对值. 然后有两种操 ...

  2. 【YBT2023寒假Day11 B】催眠大师(费用流)

    催眠大师 题目链接:YBT2023寒假Day11 B 题目大意 有一个 n*n 的棋盘,有一些位置有障碍. 然后定义棋盘上两个位置能相互攻击当且仅当在同一行或同一列,且之间的所有位置都没有障碍. 多次 ...

  3. 【YBT2023寒假Day10 B】随机游走(记忆化搜索)

    随机游走 题目链接:YBT2023寒假Day10 B 题目大意 有 n 个点排成环,你一开始在 1 号点,每次可以等概率选择左边跳两格,左边跳一格,右边跳一格,右边跳两格. 走到一个走过的点就停止. ...

  4. 【YBT2023寒假Day9 B】买棉花糖(DP)(分治)

    买棉花糖 题目链接:YBT2023寒假Day9 B 题目大意 有 n 个商店,每个商店有 ci 个物品,原价是 ai,你在一个商店买的物品越多,下一个买的就越少,每次减少 di 块钱. 然后有 q 次 ...

  5. 【YBT2023寒假Day1 B】不跪模样(树链剖分)(线段树)

    不跪模样 题目链接:YBT2023寒假Day1 B 题目大意 给你一棵有根数,点有点权,两种操作: 对于所有 x 子树内与 x 距离不超过 2 的点,将其点权加 v. 询问 x 子树中,满足 i< ...

  6. 【YBT2023寒假Day10 C】娄居吉勾(点分树)

    娄居吉勾 题目链接:YBT2023寒假Day10 C 题目大意 有一个 n 个点 m 条边的无向连通图,每个点至多在 k 个简单环上. 然后有 q 个操作,标记一个没有标记过的点,或者给你一个点求它得 ...

  7. 【YBT2023寒假Day3 A】千与千寻(期望DP)(高斯消元)

    千与千寻 题目链接:YBT2023寒假Day3 A 题目大意 一个 n*m 的平面,你要从 (0,0) 走到 (x,y),你等概率的向上或向右走,然后当你走到 (n-1,i) 再往右走,就是 (0,i ...

  8. 【YBT2023寒假Day11 A】海妖沙龙(计算几何)

    海妖沙龙 题目链接:YBT2023寒假Day11 A 题目大意 平面上有 n 个点,然后对于一个排列,如果按顺序走对于的点,会形成若干个线段组成的路径,然后你从前一个线段走到下一个线段端点时候,你需要 ...

  9. 【YBT2023寒假Day13 C】百里守约(Boruvka算法)(扫描线)(线段树)

    百里守约 题目链接:YBT2023寒假Day13 C 题目大意 有一个 n*n 的矩阵,一开始里面都是 0,多次操作,每次把一个子矩阵里面的值都增加每次给出的 w. 然后全部操作完之后构造一个 n 个 ...

最新文章

  1. python列表元素交换位置_python删除列表元素5种方法,你会的是错误法还是最优解?...
  2. Jupyter Notebook教程
  3. 请你讲一讲JavaScript有哪些数据类型, 数据类型判断有哪些方法?
  4. WayOs路由器WAN口帐号保存工具,可直接发送至邮箱,及保存接口VLAN号
  5. Mac 上无法使用netstat的-p参数
  6. 红帽启动oracle,Redhat6.5 + oracle 11gR2 设置数据库开机自启动
  7. 并发性(concurrency)和并行性(parallel)区别
  8. java参考文献英文_java论文英文的参考文献
  9. shell命令进制转换
  10. php一键领取名片赞源码,一键领取名片和圈圈赞
  11. 基于SSM的培训班管理系统
  12. amd和英伟达运行linux,AMD Ryzen平台与P106 矿卡安装Ubuntu系统和CUDA环境
  13. INSERT 语句与 FOREIGN KEY 约束冲突
  14. 男人30岁之前不必在乎的事
  15. AndroidUSB—OTG通信
  16. kaze算法的图像配准研究(2)-匹配
  17. 范寶興:3分法、4分法在12階穿越界面的浪漫
  18. tomcat Error :but has failed to stop it,This is very likely to create a memory leak.
  19. 光学定位与追踪技术_光学追踪技术
  20. MySql性能优化及常见面试题

热门文章

  1. 选做 有五个人围坐在一起,第五个比第四个大2岁;第四比第三大2岁.......第一人10岁,利用递归求第五人
  2. 梦幻西游这款游戏如何?
  3. 工具学习——Linux Read-only file system NTFS
  4. 机器学习算法实战项目—支持向量机(2)—完整版的SMO算法
  5. inodemac_Inode7.0 for mac
  6. c语言指针与数组的深入理解
  7. C语言飞机票查询与销售系统
  8. 【SWAT水文模型】SWAT水文模型建立及应用第五期:SWAT模型运行设置
  9. html5 手机录音上传 源码,Html5网页JavaScript录制MP3并上传
  10. 字节跳动多篇论文入选 CVPR 2021,精选干货都在这里了