LOJ 2958

线段树 + 类欧

主要矛盾就是$\sum\limits_{i = l}^{r}Ai \mod B$怎么做。

拆成前缀和相减的形式,有

$$\sum_{i = 0}^{r}(Ai \mod B) - \sum_{i = 0}^{l - 1}(Ai \mod B)$$

我们知道

$$a \mod b = a - \left \lfloor \frac{a}{b} \right \rfloor b$$

那么

$$\sum_{i = 0}^{n}Ai \mod B = \sum_{i = 0}^{n} Ai - \left \lfloor \frac{Ai}{B} \right \rfloor B = \frac{An(n + 1)}{2} - B\sum_{i = 0}^{n}\left \lfloor \frac{Ai}{B} \right \rfloor$$

后面那个东西就是类欧模板中的$f(A, 0, B, n)$。

还有一件事情:$10^9 * 2 * 10^9 / 2 * 10^6 = 10^{24} > long\ long$,所以我写了一个$\text{__int128}$。

因为标记一定要下传,所以似乎不能动态开点而需要离散,但是离散之后注意到线段树一个结点左右儿子可能并不是连续的。

举个栗子,假如我们离散完之后的序列是${1, 5, 7, 9}$,那么一号结点对应的区间是$[1, 9]$,而它的左儿子是$[1, 5]$,右儿子是$[7, 9]$,中间还有一段$[6, 6]$的空缺。所以我们在$up$和算答案的时候需要考虑这段空缺的贡献(可能是我线段树没学好qwq)。

这样子的话效率就很迷人了。

时间复杂度$O(qlog^2n)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef __int128 ILL; const int N = 1e5 + ; int n, qn, tot = , buc[N]; struct Options {
int op, l, r, A, B;
} q[N]; namespace Fread {
const int L = << ; char buffer[L], *S, *T; inline char Getchar() {
if(S == T) {
T = (S = buffer) + fread(buffer, , L, stdin);
if(S == T) return EOF;
}
return *S++;
} template <class T>
inline void read(T &X) {
char ch; T op = ;
for(ch = Getchar(); ch > '' || ch < ''; ch = Getchar())
if(ch == '-') op = -;
for(X = ; ch >= '' && ch <= ''; ch = Getchar())
X = (X << ) + (X << ) + ch - '';
X *= op;
} } using namespace Fread; namespace Fwrite {
const int L = << ; char buf[L], *pp = buf; void Putchar(const char c) {
if(pp - buf == L) fwrite(buf, , L, stdout), pp = buf;
*pp++ = c;
} template<typename T>
void print(T x) {
if(x < ) {
Putchar('-');
x = -x;
}
if(x > ) print(x / );
Putchar(x % + '');
} void fsh() {
fwrite(buf, , pp - buf, stdout);
pp = buf;
} template <typename T>
inline void write(T x, char ch = ) {
print(x);
if (ch != ) Putchar(ch);
fsh();
} } using namespace Fwrite; namespace LikeGcd {
ILL solve(ILL a, ILL b, ILL c, ILL n) {
if (!a) return (b / c) * (n + );
if (a >= c || b >= c)
return (a / c) * n * (n + ) / + (b / c) * (n + ) + solve(a % c, b % c, c, n);
if (a < c && b < c) {
ILL m = (a * n + b) / c;
return n * m - solve(c, c - b - , a, m - );
}
return ;
}
} namespace SegT {
struct Node {
int st, A, B;
ll sum;
bool tag;
} s[N << ]; #define lc p << 1
#define rc p << 1 | 1
#define mid ((l + r) >> 1)
#define st(p) s[p].st
#define A(p) s[p].A
#define B(p) s[p].B
#define sum(p) s[p].sum
#define tag(p) s[p].tag inline ll calc(int p, int st, int en) {
// int st = st(p), en = st(p) + buc[r] - buc[l];
if (!B(p)) return ;
ILL res = ;
res += (ILL)A(p) * (ILL)(st + en) * (ILL)(en - st + ) / (ILL);
res -= (ILL)B(p) * (LikeGcd :: solve(A(p), , B(p), en) - LikeGcd :: solve(A(p), , B(p), st - ));
return 1LL * res;
} inline void up(int p, int l, int r) {
sum(p) = sum(lc) + sum(rc);
if (buc[mid] + != buc[mid + ]) {
sum(p) += calc(p, st(p) + buc[mid] + - buc[l], st(p) + buc[mid + ] - - buc[l]);
}
} inline void down(int p, int l, int r) {
if (!tag(p)) return;
st(lc) = st(p), st(rc) = st(p) + buc[mid + ] - buc[l];
A(lc) = A(rc) = A(p);
B(lc) = B(rc) = B(p);
tag(lc) = tag(rc) = ;
sum(lc) = calc(lc, st(lc), st(lc) + buc[mid] - buc[l]);
sum(rc) = calc(rc, st(rc), st(rc) + buc[r] - buc[mid + ]);
tag(p) = ;
} void modify(int p, int l, int r, int x, int y, int A, int B) {
if (x <= l && y >= r) {
tag(p) = ;
st(p) = buc[l] - buc[x] + , A(p) = A, B(p) = B;
sum(p) = calc(p, st(p), st(p) + buc[r] - buc[l]);
return;
} down(p, l, r); if (x <= mid) modify(lc, l, mid, x, y, A, B);
if (y > mid) modify(rc, mid + , r, x, y, A, B);
if (buc[mid + ] != buc[mid] + ) {
if (buc[x] <= buc[mid] + && buc[y] >= buc[mid + ] - ) {
A(p) = A, B(p) = B;
st(p) = buc[l] - buc[x] + ;
}
} up(p, l, r);
} ll query(int p, int l, int r, int x, int y) {
if (x <= l && y >= r) return sum(p);
down(p, l, r); ll res = ;
if (x <= mid) res += query(lc, l, mid, x, y);
if (y > mid) res += query(rc, mid + , r, x, y);
if (buc[mid + ] != buc[mid] + ) {
if (buc[y] >= buc[mid] + && buc[x] <= buc[mid + ] - ) {
int ln = max(buc[mid] + , buc[x]);
int rn = min(buc[mid + ] - , buc[y]);
res += calc(p, st(p) + ln - buc[l], st(p) + rn - buc[l]);
}
} return res;
} void ddd(int p, int l, int r) {
if (l == r) return;
down(p, l, r);
ddd(lc, l, mid), ddd(rc, mid + , r);
} } using namespace SegT; int main() {
/* #ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif */ read(n), read(qn);
for (int i = ; i <= qn; i++) {
read(q[i].op), read(q[i].l), read(q[i].r);
buc[++tot] = q[i].l, buc[++tot] = q[i].r;
if (q[i].op == ) read(q[i].A), read(q[i].B);
} sort(buc + , buc + + tot);
tot = unique(buc + , buc + + tot) - buc - ; // for (int i = 1; i <= tot; i++)
// printf("%d%c", buc[i], " \n"[i == tot]); for (int i = ; i <= qn; i++) {
q[i].l = lower_bound(buc + , buc + + tot, q[i].l) - buc;
q[i].r = lower_bound(buc + , buc + + tot, q[i].r) - buc;
} for (int i = ; i <= qn; i++) {
if (q[i].op == ) modify(, , tot, q[i].l, q[i].r, q[i].A, q[i].B);
else write(query(, , tot, q[i].l, q[i].r), '\n'); /* ddd(1, 1, tot);
printf("\n");
for (int j = 1; j <= 9; j++)
printf("%d %lld %d %d %d\n", j, sum(j), A(j), B(j), st(j)); */
} return ;
}

Luogu 4433 [COCI2009-2010#1] ALADIN的更多相关文章

  1. [Luogu P4180][BJWC 2010]严格次小生成树

    严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...

  2. luogu P4385 [COCI2009]Dvapravca

    传送门 我真的弱,正解都不会还打了个错的暴力 考虑平行线与x轴平行,那么可以按照y为第一关键字升序,x为第二关键字升序排序,然后合法的一段红点就是连续的一段,答案也就是最大的连续红色段 推广到一般情况 ...

  3. POJ 1703 Find them, Catch them(并查集高级应用)

    手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/suncongbo/article/details/76735893 URL: http ...

  4. [luogu]P1800 software_NOI导刊2010提高(06)[DP][二分答案]

    [luogu]P1800 software_NOI导刊2010提高(06) 题目描述 一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块, ...

  5. Luogu P1801 黑匣子_NOI导刊2010提高(06)

    P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个 ...

  6. 【luogu P1774 最接近神的人_NOI导刊2010提高(02)】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1774 归并排序求逆序对. #include <cstdio> #define livelove ...

  7. 【luogu P1801 黑匣子_NOI导刊2010提高(06)】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1801 替罪羊树吼啊! #include <cstdio> #include <cstrin ...

  8. 【luogu P1807 最长路_NOI导刊2010提高(07)】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1807 求最大路?就是把权值取相反数跑最短路. #include <cstdio> #includ ...

  9. Luogu P1776 宝物筛选_NOI导刊2010提高(02)(多重背包模版)

    传送门 多重背包板子题, 多重背包就是每种东西有好几个,可以把它拆分成一个一个的01背包 优化:二进制拆分(拆成1+2+4+8+16+...) 比如18=1+2+4+8+3,可以证明18以内的任何数都 ...

随机推荐

  1. python 安装psutil包报错:

    报错: Failed building wheel for psutil Google得知,需要安装python-devel 和 wheel sudo dnf install python-devel ...

  2. person小项目

    所用的IDE为idea,数据库用的是Navicat for MySQL. 好了,开始正题,今天要做person小项目,有以下几个步骤: Navicat for MySQL数据库的构建,以及如何建per ...

  3. 6-18 Two Stacks In One Array(20 分)

    Write routines to implement two stacks using only one array. Your stack routines should not declare ...

  4. graphql cli 开发graphql api flow

    作用 代码生成 schema 处理 脚手架应用创建 项目管理 安装cli npm install -g graphql-cli 初始化项目(使用.graphqlconfig管理) 以下为demo de ...

  5. flow flow-typed 定义简单demo

    flow-typed 安装 全局 npm install -g flow-typed 测试代码 一个简单全局函数 目录根目录 flow-typed userLibDef.js declare func ...

  6. 在Outlook中修改脱机文件(.ost)的保存位置

    方法一 少读者所在公司的邮箱客户端都在使用微软 Exchange Server 的“缓存 Exchange 模式”.Outlook会默认将脱机文件(.ost文件)保存在C盘上. 但很多读者不希望Out ...

  7. TestCase和TestSuite详解

    一.TestCast和TestSuite概念介绍 TestCase:字面意思,测试用例.为一个或多个方法提供测试方法,一般是一个test. TestSuite:测试集合,即一组测试.一个test su ...

  8. LINQ to SQL 系列 如何使用LINQ to SQL插入、修改、删除数据 (转)

    http://www.cnblogs.com/yukaizhao/archive/2010/05/13/linq_to_sql_1.html LINQ和 LINQ to SQL 都已经不是一个新事物了 ...

  9. docker基于Dockerfile命令创建支持ssh服务的镜像

    首先,创建一个sshd_centos工作目录: [root@localhost ~]# mkdir sshd_centos [root@localhost ~]# cd sshd_centos [ro ...

  10. Java反射机制的适用场景及其利与弊 ***

    一.反射的适用场景是什么? 1).Java的反射机制在做基础框架的时候非常有用,有一句话这么说来着:反射机制是很多Java框架的基石.而一般应用层面很少用,不过这种东西,现在很多开源框架基本都已经给你 ...