首页 > 其他分享 >E. Paimon Segment Tree

E. Paimon Segment Tree

时间:2022-11-11 00:11:52浏览次数:63  
标签:rt val int Tree que query Paimon Segment op

传送门

题意:
首先给出n, m, q, 一个长度为n的数组,m次修改操作,每次修改操作,l, r, x, 对l, r区间里面的数加上k, q次询问操作,每次询问操作,问
\(\sum\limits_{i = lk}^{rk}\sum\limits_{j = xk}^{yk}a_{i, j}^2\)

思路:
等过段时间在写,先贴代码,提醒下线段树维护矩阵

总结:
线段树维护矩阵元素,重载运算符,细节写法

点击查看代码
#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define endl '\n'
#define ls rt << 1
#define rs rt << 1 | 1
#define lson ls, l, mid
#define rson rs, mid + 1, r
using namespace std;

typedef long long ll;

const ll MAXN = 1E5 + 10, MOD = 1e9 + 7;
ll n, m, q;
ll a[MAXN], ans[MAXN];

struct Mat {
	ll v[4][4];
	Mat() { memset(v, 0, sizeof(v)); }
	Mat(ll k) {
		v[0][0] = v[1][1] = v[2][2] = v[3][3] = v[2][3] = 1;
		v[0][1] = k;
		v[0][2] = v[0][3] = k * k % MOD;
		v[1][2] = v[1][3] = 2 * k % MOD;
		v[1][0] = v[2][0] = v[2][1] = v[3][0] = v[3][1] = v[3][2] = 0;
	}

	void init()
	{
		for (int i = 0; i < 4; ++i)
			for (int j = 0; j < 4; ++j)
				v[i][j] = (i == j ? 1 : 0);
	}

	ll* operator [] (int x) { return v[x]; }
	const ll* operator [] (int x) const { return v[x]; }

	Mat operator * (const Mat& b)
	{
		const Mat& a = *this;
		Mat res;
		for (int i = 0; i < 4; ++i)
			for (int j = 0; j < 4; ++j)
				for (int k = 0; k < 4; ++k)
					res.v[i][j] = (res.v[i][j] + a.v[i][k] * b.v[k][j]) % MOD;
		return res;
	}
};

struct Node {
	int val[4];
	Node() { memset(val, 0, sizeof val); }
	Node(ll x) { val[0] = 1, val[1] = x, val[2] = val[3] = x * x % MOD; }
	Node operator + (Node b)
	{
		Node res;
		for (int i = 0; i < 4; ++i)
			res.val[i] = (val[i] + b.val[i]) % MOD;
		return res;
	}

	Node operator * (Mat b)
	{
		ll res[4] = { 0 };
		for (int i = 0; i < 4; ++i)
			for (int j = 0; j < 4; ++j)
				res[j] = (res[j] + val[i] * b.v[i][j]) % MOD;
		for (int i = 0; i < 4; ++i)
			val[i] = res[i];
		return *this;
	}

} tree[MAXN << 2];

Mat lazy[MAXN << 2];

inline void push_up(int rt) 
{
	tree[rt] = tree[ls] + tree[rs]; 
}

inline void push(int rt, Mat k) 
{
	tree[rt] = tree[rt] * k, lazy[rt] = lazy[rt] * k; 
}

inline void push_down(int rt) {
	push(ls, lazy[rt]), push(rs, lazy[rt]);
	lazy[rt].init();
	return;
}

void build(int rt, int l, int r)
{
	lazy[rt].init();
	if (l == r)
	{
		tree[rt] = Node(a[l]);
		return;
	}
	int mid = l + r >> 1;
	build(lson), build(rson);
	push_up(rt);
}

void update(int rt, int l, int r, int L, int R, ll val) 
{
	if (r < L || l > R || (l >= L && r <= R))	//这里直接少调用了两个函数
		return push(rt, Mat((l >= L && r <= R) * val));
	push_down(rt);
	int mid = l + r >> 1;
	update(lson, L, R, val), update(rson, L, R, val);
	push_up(rt);
}

Node query(int rt, int l, int r, int x, int y)
{
	if (x <= l && r <= y)
		return tree[rt];
	push_down(rt);
	int mid = l + r >> 1;
	Node ans;
	if (x <= mid)
		ans = (ans + query(ls, l, mid, x, y));
	if (y >= mid + 1)
		ans = (ans + query(rs, mid + 1, r, x, y));
	return ans;
}

struct modify 
{
	int l, r, val; 
} op[MAXN];

struct query 
{
	int op, id, x, l, r;
	const bool operator< (const query& s) const { return x < s.x; }
} que[MAXN];

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> m >> q;
	for (int i = 1; i <= n; i++)
		cin >> a[i], a[i] = (a[i] + MOD) % MOD;
	build(1, 1, n);
	for (int i = 1, l, r, k; i <= m; ++i)
		cin >> op[i].l >> op[i].r >> op[i].val, op[i].val = (op[i].val + MOD) % MOD;
	for (int i = 1, l, r, x, y; i <= q; i++) 
	{
		cin >> l >> r >> x >> y;
		que[i * 2 - 1] = { -1, i, x - 1, l, r };
		que[i * 2] = { 1, i, y, l, r };
	}
	sort(que + 1, que + 1 + 2 * q);
	int pos = 1; 
	while (pos <= 2 * q && que[pos].x < 0)	//如果当前的x小于0,那只可能是减的操作,但其实,根本不用考虑
		++pos;
	for (int i = 0; i <= m; i++) 
	{
		if (i)
		{
			update(1, 1, n, op[i].l, op[i].r, op[i].val);
			//update(1, 1, n, 1, op[i].l - 1, 0);	//边上的两个版本也要更新,就因为调用了这两个函数,直接超时了
			//update(1, 1, n, op[i].r + 1, n, 0);
		}
		while (pos <= 2 * q && que[pos].x == i)
			ans[que[pos].id] += que[pos].op * query(1, 1, n, que[pos].l, que[pos].r).val[3] % MOD, ++pos;
	}
	for (int i = 1; i <= q; ++i)
		cout << (ans[i] + MOD) % MOD << endl;
	return 0;
}

标签:rt,val,int,Tree,que,query,Paimon,Segment,op
From: https://www.cnblogs.com/jumo-xiao/p/16879295.html

相关文章

  • 涨姿势 之 Sourcetree 显示头像
    LZ-Says:莫名情愫,嗷呜前言生命不止,折腾不止,哇咔咔。目前Git较为好用的莫过于Sourcetree,简单方便快速,666,而今天在看Git提交记录时,突然感觉头像丑的一批,一起瞅瞅:左上......
  • 软件篇 之 Mac Sourcetree 安装使用
    LZ-Says:今天安装网,怎一个曲折。不过从而也明白了信任,感谢。前言新系统,安装、配置好多东西,有点乱。这里简单记录下过程,避免后续脑子2333白白浪费时间。点滴积累,加油开撸......
  • vue el-tree树形结构选中子节点,保持父节点选中
    <!--菜单分配弹窗--><el-dialogtitle="菜单分配":visible.sync="menuDialogVisible"width="30%"><el-tree:props="props"......
  • C. DFS Trees
    C.DFSTreeshttps://codeforces.ml/contest/1707/problem/C题意\(findMST(i)\)代表从点i开始,按照一下算法,生成的生成树(不一定是最小生成树)。问i取1~n,findMST(i)是......
  • HDU 5379 Mahjong tree
    ProblemDescriptionLittlesunisanartist.Todayheisplayingmahjongalone.Hesuddenlyfeelsthatthetreeintheyarddoesn'tlookgood.Sohewant......
  • ClickHouse(10)ClickHouse合并树MergeTree家族表引擎之ReplacingMergeTree详细解析
    目录建表语法数据处理策略资料分享参考文章MergeTree拥有主键,但是它的主键却没有唯一键的约束。这意味着即便多行数据的主键相同,它们还是能够被正常写入。在某些使用场合......
  • K-D Tree 学习笔记
    K-DTree学习笔记K-DTree是一种可以较高效维护高维信息的数据结构,矩形查询的时间复杂度一般是\(\displaystyle\mathcalO(n^{1-1/n})\)的(我不会证),OI中一般用到的都......
  • 【转载】npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tr
    转载https://blog.csdn.net/yqx_123/article/details/118787849原因项目的依赖关系有冲突,使用npminstall报错,使用yarn可以安装,但是无法启动。步骤接受不正确......
  • 将数组数据转化成树形结构 tranListToTreeData
    exportfunctiontranListToTreeData(list,rootValue){//list是最完整的数组letarr=[];//记录儿子list.forEach((item)=>{//记录是否有儿子......
  • Segment Tree
    线段树时空复杂度常识单点操作单log.序列线段树空间4倍常数\(O(n)\).问题大家都知道线段树区间操作是一个log复杂度的,但是如何证明呢?它为什么会将区间拆成log个......