首页 > 其他分享 >P6587 超超的序列 加强

P6587 超超的序列 加强

时间:2024-06-30 22:19:42浏览次数:19  
标签:lzy dep return 超超 i64 int std P6587 序列

P6587 超超的序列 加强

01trie + 树上维护

好题,使我调不出来。

观察 \(i\) 满足的条件,在二进制上分析,\(i\bmod 2^x\) 实际上就是从低位开始的前 \(x-1\) 位。那么所有满足条件的 \(i\) 从低位开始的前 \(x-1\) 位都相同,这类似相同的前缀。考虑建 01trie,那么所有满足条件的 \(i\) 构成第 \(x\) 层一个节点的子树,此时我们已经将下标限制转化为子树限制

在树上类似动态开点线段树维护信息。需要实现区间加,单点查询,所以搞个 lazytag 啥的就做完了。

说着简单,细节很多。如:

  1. 信息合并可以记录路径,方便回溯,简单得多,要记得 top 清零!!!
  2. 结构体实现,函数写法应和普通线段树写法相似,不然调死你。
  3. 开 longlong。

复杂度 \(O(n\log n)\)。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10;
int n, m, tot;
i64 a[N];
i64 op, x, y, v;
i64 lstans;
struct SEG {
	int d[2];
	i64 v, lzy, sz;
} t[N * 44];
void insert(int u, int dep, int i) {
	if(dep > 20) return;
	t[u].v += a[i], t[u].sz++;
	int v = t[u].d[(i >> dep) & 1];
	if(!v) {
		t[u].d[(i >> dep) & 1] = ++tot;
		v = tot;
	}	
	insert(v, dep + 1, i);
}
int st[N * 44], top;
void upd(int u, int dep) {
	st[++top] = u;
	if(dep == x) {
		while(top) t[st[top--]].v += 1LL * t[u].sz * v;
		t[u].lzy += v;
		return;
	}
	int v = t[u].d[(y >> dep) & 1];
	if(!v) return;
	upd(v, dep + 1);
}
void pd(int u, i64 v) {
	t[u].v += 1LL * t[u].sz * v;
	t[u].lzy += v;
}
i64 qry(int u, int dep) {
	if(dep == x) return t[u].v;
	int v = t[u].d[(y >> dep) & 1];
	if(!v) return 0;
	if(t[u].lzy) {
		if(t[u].d[0]) pd(t[u].d[0], t[u].lzy);
		if(t[u].d[1]) pd(t[u].d[1], t[u].lzy);
		t[u].lzy = 0;
	}
	return qry(v, dep + 1);
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	std::cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		std::cin >> a[i];
		insert(0, 0, i);
	}

	while(m--) {
		std::cin >> op >> x >> y;
		op = (lstans + op) % 2 + 1;
		if(op == 1) {
			std::cin >> v;
			top = 0;
			upd(0, 0);
		} else {
			std::cout << (lstans = qry(0, 0)) << "\n";
		}
	}
	return 0;
}

标签:lzy,dep,return,超超,i64,int,std,P6587,序列
From: https://www.cnblogs.com/FireRaku/p/18277057

相关文章

  • 2024新版Coreldraw破解安装包下载附带激活码序列号,设计神助攻!
    【设计神器】CDR2024破解版,让创意飞起来!......
  • 代码随想录算法训练营第49天 | 300.最长递增子序列 、674. 最长连续递增序列 、718.
    300.最长递增子序列今天开始正式子序列系列,本题是比较简单的,感受感受一下子序列题目的思路。视频讲解:https://www.bilibili.com/video/BV1ng411J7xPhttps://programmercarl.com/0300.最长上升子序列.html/***@param{number[]}nums*@return{number}*/varlengthOfL......
  • AI数据分析013:根据时间序列数据生成动态条形图
    文章目录一、介绍二、输入内容三、输出内容一、介绍动态条形竞赛图(BarChartRace)是一种通过动画展示分类数据随时间变化的可视化工具。它通过动态条形图的形式,展示不同类别在不同时间点的数据排名和变化情况。这种图表非常适合用来展示时间序列数据的变化,能够直......
  • C语言 | Leetcode C语言题解之第187题重复的DNA序列
    题目:题解:#defineMAXSIZE769/*选取一个质数即可*/typedefstructNode{charstring[101];intindex;structNode*next;//保存链表表头}List;typedefstruct{List*hashHead[MAXSIZE];//定义哈希数组的大小}MyHashMap;List*......
  • 给定一个实数序列,设计一个最有效的算法,找到一个总和最大的区间
    这个问题是经典的最大子数组和问题,也称为Kadane算法。我们可以使用动态规划的方法来高效地解决它。以下是解决方案的C++实现:classSolution{public:vector<int>maxSubArray(vector<double>&nums){if(nums.empty())return{};doub......
  • python json反序列化为对象
    在Python中,将JSON数据反序列化为对象通常意味着将JSON格式的字符串转换为一个Python的数据结构(如列表、字典)或者一个自定义的类实例。虽然Python的标准库json模块不提供直接将JSON数据映射到类的实例的功能,但我们可以通过一些技巧来实现这个需求。以下是一个详细的示例,展示了如何......
  • 面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
    一、写在开头在上一篇学习序列化的文章中我们提出了这样的一个问题:“如果在我的对象中,有些变量并不想被序列化应该怎么办呢?”当时给的回答是:不想被序列化的变量我们可以使用transient或static关键字修饰;transient关键字的作用是阻止实例中那些用此关键字修饰的的变量序列化;当......
  • Go自定义数据的序列化流程
    ......
  • Leetcode 力扣 128. 最长连续序列 (抖音号:708231408)
    给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为 O(n) 的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。它的长度为4。示例2:输入:nums=......
  • AcWing 5726. 连续子序列
    5726.连续子序列-AcWing题库01trie的不错的练习题。题目说了求一段连续子序列的异或和,因为异或有结合律,所以我们可以直接预处理一个前缀异或和,即\(a[l,r]=sum[r]\operatorname{xor}sum[l-1]\)。然后求一段异或和就变成了求任意两个\(sum\)的异或和,而这就可以用到0......