Myhchael原创题系列 Mychael vs Kid 【题解】

时间:2022-06-05 04:57:10

题目链接##

Mychael vs Kid

题解##

先说说这题的由来及前身

前身##

首先有一个很经典的题目:

维护区间加,查询区间\(gcd\)

如果强行用线段树维护的话,区间加之后就没法直接确定当前区间的\(gcd\),不可直接维护

这个时候就用到了\(gcd\)的一个性质:

\[(a,b) = (a - b,b)
\]

三个的\(gcd\)也是符合的:

\[(a,b,c) = (a,b,c - b) = (a,b - a,c - b)
\]

同样可以推广出\(n\)个的情况

\[gcd\{a_i\} = gcd(a_1,gcd\{a_j - a_{j - 1}\}) \qquad i \in [1,n] \quad j \in [2,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 【题解】的更多相关文章

  1. Newtonsoft&period;Json C&num; Json序列化和反序列化工具的使用、类型方法大全 C&num; 算法题系列&lpar;二&rpar; 各位相加、整数反转、回文数、罗马数字转整数 C&num; 算法题系列&lpar;一&rpar; 两数之和、无重复字符的最长子串 DateTime Tips c&num;发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  2. NOI题库 1768最大子矩阵 题解

    NOI题库 1768最大子矩阵  题解     总时间限制: 1000ms 内存限制: 65536kB   描述   已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大 ...

  3. hdu5017:补题系列之西安网络赛1011

    补题系列之西安网络赛1011 题目大意:给定一个椭球: 求它到原点的最短距离. 思路: 对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为m ...

  4. nyoj 1208——水题系列——————【dp】

    水题系列 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述     给你一个有向图,每条边都有一定的权值,现在让你从图中的任意一点出发,每次走的边的权值必须必上一次的权 ...

  5. Mychael原创题 洛谷T23923 Mychaelの水题 【题解】

    原题链接 题目大意: 有来自三个地区的人各a,b,c位,他们排成了一排.请问有多少种不同类型的排法,使得相邻的人都来自不同的地区 \(a,b,c<=200\) 答案取模 题解 弱弱的标程解法 设 ...

  6. NOI题库刷题日志 (贪心篇题解)

    这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制:  1000ms  内存限制:  65536kB 描述 在一个平面上,如果有两个点( ...

  7. C&num;版 - PAT乙级&lpar;Basic Level&rpar;真题 之 1021&period;个位数统计 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - P ...

  8. LeetCode算法扫题系列19

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104677.html LeetCode算法第19题(难度:中等) 题目:给定一个链表,删 ...

  9. LeetCode算法扫题系列83

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104582.html LeetCode算法第83题(难度:简单) 题目:给定一个排序链表 ...

随机推荐

  1. 用:before :after 来写一些小特效

    提起:before :after首先想到的是 —— 用它来去浮动来我们来换个方式玩接下来展示三种用:before :after来实现的特效 希望能起到抛砖引玉的作用 <一>第一种就是常见的 ...

  2. 完整的社交app源码android&plus;laravel

    等想到写点什么的时候再写吧,其他看代码. https://github.com/huijimuhe/monolog-android https://github.com/huijimuhe/monol ...

  3. Codeforces Round &num;344 &lpar;Div&period; 2&rpar;

    水 A - Interview 注意是或不是异或 #include <bits/stdc++.h> int a[1005], b[1005]; int main() { int n; sc ...

  4. URAL 1654 Cipher Message 解题报告

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...

  5. 轻松学Shell之认识正规表达式

    离线下载观看:http://down.51cto.com/data/148117   650) this.width=650;" onclick='window.open("htt ...

  6. 构建高性能服务(三)Java高性能缓冲设计 vs Disruptor vs LinkedBlockingQueue--转载

    原文地址:http://maoyidao.iteye.com/blog/1663193 一个仅仅部署在4台服务器上的服务,每秒向Database写入数据超过100万行数据,每分钟产生超过1G的数据.而 ...

  7. WordPress 3&period;5&period;1 crypt&lowbar;private&lpar;&rpar;远程拒绝服务漏洞&lpar;CVE-2013-2173&rpar;

    漏洞版本: WordPress 3.5.1 漏洞描述: BUGTRAQ ID: 60477 CVE(CAN) ID: CVE-2013-2173 WordPress是一种使用PHP语言和MySQL数据 ...

  8. Spring&lowbar;database&lowbar;Template

    配置applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  9. 架构设计之设计模式 &lpar;一&rpar; 适配器&lpar;Adapter&rpar;---提高复用性

    简介 简介是为了描述一下该模式是干嘛用的,为了让不了解该模式的人看了之后也有一些新的认识. 本文章分为两部分,第一部分主要介绍适配器模式:第二部分介绍该模式与相近模式的异同. 下午一直在讨论设计模式, ...

  10. ios ViewController的生命周期分析和基本使用逻辑

    按结构可以对iOS的所有ViewController分成两类:1.主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITable ...