Myhchael原创题系列 Mychael vs Kid 【题解】
题目链接##
题解##
先说说这题的由来及前身
前身##
首先有一个很经典的题目:
维护区间加,查询区间\(gcd\)
如果强行用线段树维护的话,区间加之后就没法直接确定当前区间的\(gcd\),不可直接维护
这个时候就用到了\(gcd\)的一个性质:
\]
三个的\(gcd\)也是符合的:
\]
同样可以推广出\(n\)个的情况
\]
也就是说,区间差分了之后,我们要求原区间\(gcd[l,r]\),就相当于求\(a_l\)和差分后区间\([l + 1,r]\)的\(gcd\)
所以我们只需维护差分区间和区间每个位置的值即可
维护区间值用线段树一点问题都没有
在加法下维护差分区间,一个区间加上一个数,仅影响区间端点的值,所以单点修改即可
所以我们开两棵线段树,一棵维护权值,一棵维护差值的\(gcd\),即可\(O(nlog^2n)\)解决这道题
本题##
本题多加入了一个区间乘法操作
本来想\(yy\)分块的,可后来发现线段树依旧可写并且暴艹分块
思考一下发现,区间乘法后,区间差分值也乘上那个数,对应\(gcd\)也乘上一个数,可以使用线段树维护
至于端点的差值改变,只需取出端点的值计算出差值后单点加法修改即可
复杂度依旧是\(O(nlog^2n)\)
部分分##
前\(5\%\),咳,,,
对于\(n,m \le 300\),暴力求即可
对于没有操作\(2\)的,就是原版题目
对于\(n,m \le 3 \times 10^4\)的,可以考虑分块
std
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
	return out * flag;
}
LL n,m,A[maxn],D[maxn];
LL gcd(LL a,LL b){
	if (a < 0) a = -a;
	if (b < 0) b = -b;
	return b ? gcd(b,a % b) : a;
}
struct Seg_Gcd{
	LL Gcd[maxn << 2],tag[maxn << 2];
	void upd(int u){
		Gcd[u] = gcd(Gcd[ls],Gcd[rs]);
	}
	void pd(int u){
		if (tag[u] != 1){
			Gcd[ls] *= tag[u]; tag[ls] *= tag[u];
			Gcd[rs] *= tag[u]; tag[rs] *= tag[u];
			tag[u] = 1;
		}
	}
	void build(int u,int l,int r){
		tag[u] = 1;
		if (l == r){
			Gcd[u] = D[l];
			return;
		}
		int mid = l + r >> 1;
		build(ls,l,mid);
		build(rs,mid + 1,r);
		upd(u);
	}
	void Add(int u,int l,int r,int pos,int v){
		if (l == r){Gcd[u] += v; return;}
		pd(u);
		int mid = l + r >> 1;
		if (mid >= pos) Add(ls,l,mid,pos,v);
		else Add(rs,mid + 1,r,pos,v);
		upd(u);
	}
	void Mult(int u,int l,int r,int L,int R,int v){
		if (l >= L && r <= R){Gcd[u] *= v; tag[u] *= v; return;}
		pd(u);
		int mid = l + r >> 1;
		if (mid >= L) Mult(ls,l,mid,L,R,v);
		if (mid < R) Mult(rs,mid + 1,r,L,R,v);
		upd(u);
	}
	LL query(int u,int l,int r,int L,int R){
		if (l >= L && r <= R) return Gcd[u];
		pd(u);
		int mid = l + r >> 1;
		if (mid >= R) return query(ls,l,mid,L,R);
		if (mid < L) return query(rs,mid + 1,r,L,R);
		return gcd(query(ls,l,mid,L,R),query(rs,mid + 1,r,L,R));
	}
}T2;
struct Seg{
	LL val[maxn << 2],mult[maxn << 2],add[maxn << 2];
	void pd(int u){
		if (mult[u] != 1){
			val[ls] *= mult[u]; mult[ls] *= mult[u]; add[ls] *= mult[u];
			val[rs] *= mult[u]; mult[rs] *= mult[u]; add[rs] *= mult[u];
			mult[u] = 1;
		}
		if (add[u]){
			val[ls] += add[u]; add[ls] += add[u];
			val[rs] += add[u]; add[rs] += add[u];
			add[u] = 0;
		}
	}
	void build(int u,int l,int r){
		add[u] = 0; mult[u] = 1;
		if (l == r){
			val[u] = A[l];
			return;
		}
		int mid = l + r >> 1;
		build(ls,l,mid);
		build(rs,mid + 1,r);
	}
	void Add(int u,int l,int r,int L,int R,int v){
		if (l >= L && r <= R){val[u] += v; add[u] += v; return;}
		pd(u);
		int mid = l + r >> 1;
		if (mid >= L) Add(ls,l,mid,L,R,v);
		if (mid < R) Add(rs,mid + 1,r,L,R,v);
	}
	void Mult(int u,int l,int r,int L,int R,int v){
		if (l >= L && r <= R){val[u] *= v; add[u] *= v; mult[u] *= v; return;}
		pd(u);
		int mid = l + r >> 1;
		if (mid >= L) Mult(ls,l,mid,L,R,v);
		if (mid < R) Mult(rs,mid + 1,r,L,R,v);
	}
	LL query(int u,int l,int r,int pos){
		if (l == r) return val[u];
		pd(u);
		int mid = l + r >> 1;
		if (mid >= pos) return query(ls,l,mid,pos);
		return query(rs,mid + 1,r,pos);
	}
}T1;
int main(){
	n = read(); m = read();
	for (int i = 1; i <= n; i++){
		A[i] = read();
		D[i] = A[i] - A[i - 1];
	}
	T1.build(1,1,n);
	T2.build(1,1,n);
	LL opt,l,r,v,t1,t2;
	while (m--){
		opt = read(); l = read(); r = read();
		if (opt == 1){
			v = read();
			T1.Add(1,1,n,l,r,v);
			T2.Add(1,1,n,l,v);
			if (r + 1 <= n) T2.Add(1,1,n,r + 1,-v);
		}
		else if (opt == 2){
			v = read();
			t1 = T1.query(1,1,n,l);
			if (r + 1 <= n) t2 = T1.query(1,1,n,r);
			if (l < r) T2.Mult(1,1,n,l + 1,r,v);
			T2.Add(1,1,n,l,t1 * v - t1);
			if (r + 1 <= n) T2.Add(1,1,n,r + 1,t2 - t2 * v);
			T1.Mult(1,1,n,l,r,v);
		}
		else {
			if (l < r) printf("%lld\n",gcd(T1.query(1,1,n,l),T2.query(1,1,n,l + 1,r)));
			else printf("%lld\n",T1.query(1,1,n,l));
		}
	}
	return 0;
}
Myhchael原创题系列 Mychael vs Kid 【题解】的更多相关文章
- Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全  C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数  C# 算法题系列(一) 两数之和、无重复字符的最长子串  DateTime Tips  c#发送邮件,可发送多个附件  MVC图片上传详解
		Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全 Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ... 
- NOI题库 1768最大子矩阵  题解
		NOI题库 1768最大子矩阵 题解 总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大 ... 
- hdu5017:补题系列之西安网络赛1011
		补题系列之西安网络赛1011 题目大意:给定一个椭球: 求它到原点的最短距离. 思路: 对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为m ... 
- nyoj 1208——水题系列——————【dp】
		水题系列 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 给你一个有向图,每条边都有一定的权值,现在让你从图中的任意一点出发,每次走的边的权值必须必上一次的权 ... 
- Mychael原创题 洛谷T23923 Mychaelの水题   【题解】
		原题链接 题目大意: 有来自三个地区的人各a,b,c位,他们排成了一排.请问有多少种不同类型的排法,使得相邻的人都来自不同的地区 \(a,b,c<=200\) 答案取模 题解 弱弱的标程解法 设 ... 
- NOI题库刷题日志 (贪心篇题解)
		这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制: 1000ms 内存限制: 65536kB 描述 在一个平面上,如果有两个点( ... 
- C#版 - PAT乙级(Basic Level)真题 之 1021.个位数统计 - 题解
		版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - P ... 
- LeetCode算法扫题系列19
		原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104677.html LeetCode算法第19题(难度:中等) 题目:给定一个链表,删 ... 
- LeetCode算法扫题系列83
		原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104582.html LeetCode算法第83题(难度:简单) 题目:给定一个排序链表 ... 
随机推荐
- 关于BLOB/TEXT字段存储设计及性能的简单研究
			简单研究了一下BLOB/TEXT字段对数据库性能的影响,得到一个大概的结论:(未验证) 无论MySQL还是MSSQL,都可以通过把BLOB/TEXT数据存储在行外的方式提高性能 把BLOB/TEXT字 ... 
- 纯净CentOS安装PHP网站环境
			一.MySQL数据库 安装mysql: yum install mysql mysql-server 启动mysql: /etc/init.d/mysqld start 或 service mysq ... 
- git的一些操作指令
			1. mkdir learn 创建learn文件夹(也可不用命令创建,直接右击新建即可) cd learn进入learn文件夹 git init 把learn文件夹 变成 可以用git管理的 ... 
- 接口测试工具postman(六)添加变量(参数化)
			1.添加全局变量并引用 2.通过设置请求前置配置变量 3.在Tests里面,把响应数据设置为变量 4.添加外部文件,引用外部文件中的变量和数据,此种场景就可以执行多次请求 1)配置文件,txt或者cs ... 
- Linux命令应用大词典-第17章 软件包管理
			17.1 rpm:RPM软件包管理器 17.2 rpmargs:处理RPM软件包 17.3 rpmbuild:构建RPM软件包 17.4 rpmdiff:比较两个软件包之间的不同 17.5 rpmel ... 
- Unity编辑器 - 输入控件聚焦问题
			Unity编辑器整理 - 输入控件聚焦问题 EditorGUI的输入控件在聚焦后,如果在其他地方改变值,聚焦的框不会更新,而且无法取消聚焦,如下图: 在代码中取消控件的聚焦 取消聚焦的"时机 ... 
- 【zabbix 监控】第一章 zabbix的安装配置
			安装前准备 一.下载网络yum源: http://mirrors.163.com/.help/centos.html https://opsx.alibaba.com/mirror 1.首先备份/et ... 
- 3D动态人脸识别技术分析——世纪晟人脸识别实现三维人脸建模
			- 目录 - 国内3D动态人脸识别现状概况 - 新形势下人脸识别技术发展潜力 - 基于深度学习的3D动态人脸识别技术分析 1. 非线性数据建模方法 2. 基于3D变形模型的人脸建模 - 案例结合——世 ... 
- Ext JS 6学习文档-第6章-高级组件
			Ext JS 6学习文档-第6章-高级组件 高级组件 本章涵盖了高级组件,比如 tree 和 data view.它将为读者呈现一个示例项目为 图片浏览器,它使用 tree 和 data view 组 ... 
- SGU 438 The Glorious Karlutka River =)(最大流)
			Description A group of Mtourists are walking along the Karlutka river. They want to cross the river, ... 
