首页 > 其他分享 >Daimayuan Online Judge 线段树打标记2

Daimayuan Online Judge 线段树打标记2

时间:2023-08-29 21:12:38浏览次数:47  
标签:Info 树打 int Daimayuan seg Tag Online mul id

给 \(n\) 个数 \(a_1, a_2, \cdots, a_n\) 。
支持 \(q\) 个操作:

  1. 1 l r d ,令所有的 \(a_i(l \leq i \leq r)\) 加上 \(d\) 。
  2. 2 l r d ,令所有的 \(a_i(l \leq i \leq r)\) 乘上 \(d\) 。
  3. 3 l r d ,令所有的 \(a_i(l \leq i \leq r)\) 等于 \(d\) 。
  4. 4 l r ,查询 \((\sum_{i = l}^{r} a_i) \mod (10^9 + 7)\) 。

一:确定维护的信息,确定修改信息需要的标记。确定期间的合并。

  1. 信息需要区间值和 \(sum\) ,区间大小 \(sz\) (维护和且区间加时必要)。
  2. 标记设计为 \(val \times mul + add\) 。不问为什么,问就是典。
  3. 合并:(以下默认模意义下)
    1. 信息与信息合并:\(now.sum = l.sum + r.sum\) ,\(now.sz = l.sz + r.sz\) 。
    2. 信息与标记合并:\(now.sum = f.sum \times t.mul + f.sz \times t.add\)
    3. 标记与标记合并:
      1. 非常需要注意标记合并需要按照先后顺序,比如 \(((a \times 2) + 3) \times 4 + 5\) 与 \(((a \times 4) + 5) \times 2 + 3\) 分别为 \(8a + 12\) 与 \(8a + 15\) ,显然不同。
      2. \(((a \times t1.mul) + t1.add) \times t2.mul + t2.add = (a \times t1.mul) \times t2.mul + (t1.add) \times t2.mul + t2.add\) 。于是有 \(now.mul = t1.mul \times t2.mul\) ,\(now.add = t1.add \times t2.mul + t2.add\) 。
  4. 注意多个标记时的初始化,\(a = a \times 1 + 0\) ,于是 \(build\) 时初始化 \(t = \{1, 0\}\) 。
// 主要是确定 Info 和 Tag 的信息

struct Info { 
	ll sum, sz;
};

struct Tag {
	ll mul, add;
};

struct Node {
	Info f;
	Tag t;
} seg[N * 4];

// 确定他们的合并方式

Info operator + (const Info &l, const Info &r) {
	Info ret;
	ret = { ( l.sum + r.sum ) % mod, l.sz + r.sz };
	return ret;
}

Info operator + (const Info &f, const Tag &t) {
	Info ret;
	ret = { ( ( f.sum * t.mul ) % mod + ( f.sz * t.add ) % mod ) % mod, f.sz };
	return ret;
}

Tag operator + (const Tag &t1, const Tag &t2) {
	Tag ret;
	ret = { ( t1.mul * t2.mul ) % mod, ( t1.add * t2.mul + t2.add ) % mod };
	return ret;
}

void update(int id) {
	seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1].f;
} 

void settag(int id, Tag t) {
	seg[id].f = seg[id].f + t;
	seg[id].t = seg[id].t + t;
}

void pushdown(int id) {
	if (seg[id].t.mul != 1 || seg[id].t.add != 0) { // 标记非空,一个习惯 
		settag( id * 2, seg[id].t );
		settag( id * 2 + 1, seg[id].t );
		seg[id].t = {1, 0};
	}
}

只需要推理出 \(Info\) 和 \(Tag\) 与目标信息的关系。

然后改一下 \(Info\) 、 \(Tag\) 、合并方式,调整一下初始化,就可以直接贴代码了。

注意 \(build\) 里有 \(Info\) 和 \(Tag\) 的初始化,\(pushdown\) 里有 \(Tag\) 初始化和 \(Tag\) 非空的判断。

view
#include <bits/stdc++.h>
typedef long long ll;
const int N = 200005;
const int mod = 1E9 + 7;

int a[N]; 

struct Info {
	ll sum, sz;
};

struct Tag {
	ll mul, add;
};

struct Node {
	Info f;
	Tag t;
} seg[N * 4];

Info operator + (const Info &l, const Info &r) {
	Info ret;
	ret = { ( l.sum + r.sum ) % mod, l.sz + r.sz };
	return ret;
}

Info operator + (const Info &f, const Tag &t) {
	Info ret;
	ret = { ( ( f.sum * t.mul ) % mod + ( f.sz * t.add ) % mod ) % mod, f.sz };
	return ret;
}

Tag operator + (const Tag &t1, const Tag &t2) {
	Tag ret;
	ret = { ( t1.mul * t2.mul ) % mod, ( t1.add * t2.mul + t2.add ) % mod };
	return ret;
}

void update(int id) {
	seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1].f;
} 

void settag(int id, Tag t) {
	seg[id].f = seg[id].f + t;
	seg[id].t = seg[id].t + t;
}

void pushdown(int id) {
	if (seg[id].t.mul != 1 || seg[id].t.add != 0) { // 标记非空,一个习惯 
		settag( id * 2, seg[id].t );
		settag( id * 2 + 1, seg[id].t );
		seg[id].t = {1, 0};
	}
}

void build(int id, int l, int r) {
	seg[id].t = {1, 0};
	if (l == r) {
		seg[id].f = {a[l], 1};
	}
	else {
		int mid = ( l + r ) >> 1;
		build( id * 2, l, mid );
		build( id * 2 + 1, mid + 1, r );
		update(id);
	}
} 

Info query(int id, int l, int r, int ql, int qr) {
	if (l == ql && r == qr) {
		return seg[id].f;
	}
	else {
		pushdown(id);
		int mid = ( l + r ) >> 1;
		if ( qr <= mid ) return query( id * 2, l, mid, ql, qr );
		else if ( ql > mid ) return query( id * 2 + 1, mid + 1, r, ql, qr );
		else return query( id * 2, l, mid, ql, mid ) + query( id * 2 + 1, mid + 1, r, mid + 1, qr);
	}
}

void modify(int id, int l, int r, int ql, int qr, Tag t) {
	if (l == ql && r == qr) {
		settag( id, t );
	}
	else {
		pushdown(id);
		int mid = ( l + r ) >> 1;
		if ( qr <= mid ) modify( id * 2, l, mid, ql, qr, t );
		else if ( ql > mid) modify( id * 2 + 1, mid + 1, r, ql, qr, t );
		else modify( id * 2, l, mid, ql, mid, t ), modify( id * 2 + 1, mid + 1, r, mid + 1, qr, t );
		update(id);
	}
}

int main() {
	int n, q;
	std::cin >> n >> q;
	for (int i = 1; i <= n; i++) std::cin >> a[i];
	build(1, 1, n);
	for (int i = 1; i <= q; i++) {
		int typ; std::cin >> typ;
		if ( typ == 1 ) {
			int l, r, d; std::cin >> l >> r >> d;
			modify(1, 1, n, l, r, {1, d});
		}
		else if ( typ == 2 ) {
			int l, r, d; std::cin >> l >> r >> d;
			modify(1, 1, n, l, r, {d, 0});
		}
		else if ( typ == 3 ) {
			int l, r, d; std::cin >> l >> r >> d;
			modify(1, 1, n, l, r, {0, d});
		}
		else {
			int l, r; std::cin >> l >> r;
			auto ans = query(1, 1, n, l, r);
			std::cout << ans.sum << '\n';
		}
	}
	return 0;
}


标签:Info,树打,int,Daimayuan,seg,Tag,Online,mul,id
From: https://www.cnblogs.com/zsxuan/p/17665670.html

相关文章

  • Daimayuan Online Judge 线段树打标记1
    给\(n\)个数\(a_1,a_2,\cdots,a_n\)。支持\(q\)个操作:1lrd,令所有的\(a_i(l\leqi\leqr)\)加上\(d\)。2lr,查询\(max_{i=l}^{r}a_i\)。区间修改的线段树要比基础线段树多考虑一个元素:\(lazy\tag\)。复杂的信息可以用多个标记表示。\(lazy\ta......
  • Daimayuan Online Judge 线段树2
    给\(n\)个数\(a_1,a_2,\cdots,a_n\)。支持\(q\)个操作:1xd,修改\(a_x=d\)。2lr,查询\([l,r]\)中的最大子段和。一:确定需要维护的信息。根据分治中线讨论,哪些信息可以合并出所需信息。递归讨论新信息如何合并。直至完全拆解。不越过分治中线:\([l,r]\)......
  • Daimayuan Online Judge 线段树1
    给\(n\)个数\(a_1,a_2,\cdots,a_n\)。支持\(q\)个操作:1.1xd,修改\(a_x=d\)。2.2lr,查询\(min_{i=l}^{r}a_i\),并输出\(\sum_{i=l}^{r}[a_i=min_{i=l}^{r}a_i]\)。一:确定出需要维护的信息\(Info\)。建立线段树节点structInfo{ intminv......
  • MySQL online DDl原理
    onlineDDL从5.6开始,不阻塞DML但是会阻塞所有的DDL,online有三种模式:INSTANT(8.0.12),INPLACE(rebuild),INPLACE(no-rebuild),具体操作如下:1、只修改表的元数据信息删除二级索引修改索引名(5.7)修改字段名设置(删除)字段的默认值增加varchar长度,如果表示字符串长度的字节数变化则会使用c......
  • 无涯教程-PHP Online Test函数
    该PHP在线测试模拟了真正的在线认证考试。您将看到基于PHP概念的多项选择题(MCQ),将为您提供四个options。您将为该问题选择最合适的答案,然后继续进行下一个问题,而不会浪费时间。完成完整的考试后,您将获得在线考试分数。总问题数-20最长时间-20分钟StartTest参......
  • 无涯教程-PHP Online Quiz函数
    以下测验提供与PHP相关的多项选择题(MCQ)。您将必须阅读所有给定的答案,然后单击正确的答案。如果您不确定答案,则可以使用显示答案按钮检查答案。您可以使用下一个测验按钮检查测验中的新问题集。Q1-关于PHP,以下哪项是正确的?A-PHP可以访问cookie变量并设置cookie。......
  • daimayuan252 | 摸鱼(状压, 枚举, 小技巧)
    题目很straightforward的,看到n范围很小考虑状压,暴力枚举所有的可能pattern.第一种做法,暴力枚举是\(O(2^n)\)的,然后check函数判断是\(O(n^2)\)的,一共是\(O(n^22^n)\)的,可以通过.第二种做法,我们考虑把判断pattern是否合法的限制条件也压成二进制串,那么我们比对条......
  • The 2022 ICPC Asia Regionals Online Contest (II) EJFB
    The2022ICPCAsiaRegionalsOnlineContest(II)EAnInterestingSequence232323232323323232323232#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;voidsolve(){ lln,k; cin>>n>>k; llres=k; llt=0; for(......
  • The 2022 ICPC Asia Regionals Online Contest (I) C L A
    The2022ICPCAsiaRegionalsOnlineContest(I)C统计度的大小,算贡献,特判\(n=1\)#include<bits/stdc++.h>usingnamespacestd;constintN=1e6+10;typedeflonglongll;intn,d[N];vector<int>e[N];llres=0;voiddfs(intu,intfrom){ ......
  • Intention-Aware Online POMDP Planning for Autonomous Driving in a Crowd
    一、论文信息发表日期:2015年发表机构:新加坡国立大学,计算机科学系二、论文内容1.解决问题:无人车在人员密集处的速度规划算法2.方法:前向仿真+强化学习概念   ①.路径规划和速度规划进行解耦,进行速度规划之前路径已确定。 ②.速度规划采取部分可观测马尔可夫决策过程,......