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. 算法初探:Tensorflow及PAI平台的使用

    前言 Tensorflow这个词由来已久,但是对它的理解一直就停留在“听过”的层面.之前做过一个无线图片适配问题智能识别的项目,基于Tensorflow实现了GoogLeNet - Inception ...

  2. Linux下驱动模块学习

    1.modutils中提供了相关的insmod,rmmod,modinfo工具2.modprobe在识别出目标模块所依赖模块后也是调用insmod.3.从外部看模块只是普通可重定位的目标文件.可重定位 ...

  3. nexus yum 私服集成

      nexus 集成了 yum 私服使用起来还是比较简单的 配置 yum proxy 实际使用我们可能需要配置centos 以及epel 的源 centos可以用http://mirror.cento ...

  4. MySql登陆密码忘记了 怎么办?

    MySql登陆密码忘记了 怎么办?root密码:连root密码忘记没用root进修改mysql数据库user表咯 root密码: 方法一:MySQL提供跳访问控制命令行参数通命令行命令启MySQL服务 ...

  5. intellij系列ide配置

    显示行号 搜索line number 在Editor,General,Appearance里面,勾选show line numbers 修改自体 sudo apt-get install fonts- ...

  6. memcached内存管理机制分析

    memached是高性能分布式内存对象系统,通过在内存中存储数据对象来减少对磁盘的数据读取次数,提高服务速度. 从业务需求出发.我们通过一条命令(如set)将一条键值对(key,value)插入mem ...

  7. wamp ssl配置https

    主要参考的这个博客 http://blog.csdn.net/sdq4700/article/details/36173665 配置完以后重启wamp , https不能正常访问 apache.log ...

  8. C# 基础备忘录

    1. decimal 类型调用ToString()方法后没把末尾的0去掉的解决办法: 例子:decimal? money = Convert.ToDecimal(10.8950); string mo ...

  9. ThinkPHP实现事务回滚示例代码

    ThinkPHP的事务回滚示例如下: ? 1 2 3 4 5 6 7 8 9 10 $m=D('YourModel');//或者是M(); $m2=D('YouModel2'); $m->sta ...

  10. Keras Sequential顺序模型

    keras是基于tensorflow封装的的高级API,Keras的优点是可以快速的开发实验,它能够以TensorFlow, CNTK, 或者 Theano 作为后端运行. 模型构建 最简单的模型是  ...