Luogu 4433 [COCI2009-2010#1] ALADIN
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 + 5;int n, qn, tot = 0, buc[N];struct Options {int op, l, r, A, B; } q[N];namespace Fread {const int L = 1 << 15;char buffer[L], *S, *T;inline char Getchar() {if(S == T) {T = (S = buffer) + fread(buffer, 1, L, stdin);if(S == T) return EOF;}return *S++;}template <class T> inline void read(T &X) {char ch; T op = 1;for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())if(ch == '-') op = -1;for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) X = (X << 1) + (X << 3) + ch - '0'; X *= op;}} using namespace Fread; namespace Fwrite {const int L = 1 << 15;char buf[L], *pp = buf;void Putchar(const char c) {if(pp - buf == L) fwrite(buf, 1, L, stdout), pp = buf;*pp++ = c;}template<typename T>void print(T x) {if(x < 0) {Putchar('-');x = -x;}if(x > 9) print(x / 10);Putchar(x % 10 + '0');}void fsh() {fwrite(buf, 1, pp - buf, stdout);pp = buf;}template <typename T>inline void write(T x, char ch = 0) {print(x);if (ch != 0) Putchar(ch);fsh();}} using namespace Fwrite;namespace LikeGcd {ILL solve(ILL a, ILL b, ILL c, ILL n) {if (!a) return (b / c) * (n + 1);if (a >= c || b >= c) return (a / c) * n * (n + 1) / 2 + (b / c) * (n + 1) + 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 - 1, a, m - 1);}return 0;} }namespace SegT {struct Node {int st, A, B;ll sum;bool tag;} s[N << 2];#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].taginline ll calc(int p, int st, int en) { // int st = st(p), en = st(p) + buc[r] - buc[l];if (!B(p)) return 0;ILL res = 0;res += (ILL)A(p) * (ILL)(st + en) * (ILL)(en - st + 1) / (ILL)2;res -= (ILL)B(p) * (LikeGcd :: solve(A(p), 0, B(p), en) - LikeGcd :: solve(A(p), 0, B(p), st - 1));return 1LL * res;}inline void up(int p, int l, int r) {sum(p) = sum(lc) + sum(rc);if (buc[mid] + 1 != buc[mid + 1]) {sum(p) += calc(p, st(p) + buc[mid] + 1 - buc[l], st(p) + buc[mid + 1] - 1 - 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 + 1] - buc[l];A(lc) = A(rc) = A(p);B(lc) = B(rc) = B(p);tag(lc) = tag(rc) = 1;sum(lc) = calc(lc, st(lc), st(lc) + buc[mid] - buc[l]);sum(rc) = calc(rc, st(rc), st(rc) + buc[r] - buc[mid + 1]);tag(p) = 0;}void modify(int p, int l, int r, int x, int y, int A, int B) {if (x <= l && y >= r) {tag(p) = 1;st(p) = buc[l] - buc[x] + 1, 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 + 1, r, x, y, A, B);if (buc[mid + 1] != buc[mid] + 1) {if (buc[x] <= buc[mid] + 1 && buc[y] >= buc[mid + 1] - 1) {A(p) = A, B(p) = B;st(p) = buc[l] - buc[x] + 1;}}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 = 0;if (x <= mid) res += query(lc, l, mid, x, y);if (y > mid) res += query(rc, mid + 1, r, x, y);if (buc[mid + 1] != buc[mid] + 1) {if (buc[y] >= buc[mid] + 1 && buc[x] <= buc[mid + 1] - 1) {int ln = max(buc[mid] + 1, buc[x]);int rn = min(buc[mid + 1] - 1, 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 + 1, r);}} using namespace SegT;int main() { /* #ifndef ONLINE_JUDGEfreopen("input.txt", "r", stdin);#endif */read(n), read(qn);for (int i = 1; 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 == 1) read(q[i].A), read(q[i].B);}sort(buc + 1, buc + 1 + tot);tot = unique(buc + 1, buc + 1 + tot) - buc - 1;// for (int i = 1; i <= tot; i++) // printf("%d%c", buc[i], " \n"[i == tot]); for (int i = 1; i <= qn; i++) {q[i].l = lower_bound(buc + 1, buc + 1 + tot, q[i].l) - buc;q[i].r = lower_bound(buc + 1, buc + 1 + tot, q[i].r) - buc;}for (int i = 1; i <= qn; i++) {if (q[i].op == 1) modify(1, 1, tot, q[i].l, q[i].r, q[i].A, q[i].B);else write(query(1, 1, 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 0; }
View Code
转载于:https://www.cnblogs.com/CzxingcHen/p/10388319.html
Luogu 4433 [COCI2009-2010#1] ALADIN相关推荐
- POJ 1703 Find them, Catch them(并查集高级应用)
POJ 1703 Find them, Catch them(并查集高级应用) 手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/sunc ...
- luogu P1774 最接近神的人_NOI导刊2010提高(02)
题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着"神的殿堂".小FF猜 ...
- Luogu P4859「已经没有什么好害怕的了」
以前开过一遍这题,以为很难没刚下去 今天$ review$一遍分析了一下感觉也还好 luogu 4859 题意:给定长度为$ n \leq 2000$的数组$ A,B$求完全匹配使得$A>B$的 ...
- 【DP】字串距离(luogu 1279)
字串距离 luogu 1279 题目大意 给出两个字符串,让你加上若干空格,使其长度相同 对于第i位,如果都是字母那代价就是ASCII码的差值,如果一个是字母那就是k,如果没有一个是字母那就是0,让你 ...
- 【数学】拉格朗日插值(luogu 4781/金牌导航 拉格朗日插值-1)
拉格朗日插值 luogu 4781 金牌导航 拉格朗日插值-1 题目大意 给出n个点,让你确定经过这n个点且不超过n-1次的方程,现在给出k,让你求出其函数值 样例#1 输入样例#1 3 100 1 ...
- 【斜率优化】仓库建设(luogu 2120)
仓库建设 luogu 2120 题目大意 有一个斜坡,上面有n个工厂(山顶是1,山脚是nnn,工厂都是漏填),上面有pip_ipi个货物,和工厂1的距离为x1x_1x1 现在有一场大雨,你可以在某 ...
- 简介SharePoint 2010 14 Hive文件夹
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u012025054/article/details/36018873 简介SharePoint 20 ...
- luogu P1549 棋盘问题(2) 题解
luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...
- [Luogu] 选学霸
https://www.luogu.org/problemnew/show/P2170 并查集+DP #include <iostream> #include <cstring> ...
最新文章
- java 移动支付接口开发,移动支付平台间接口报文解析技术核心架构实现、及平台交易处理项目全程实录教程...
- python论坛哪些好-好的python论坛
- 最好用的20个数据可视化工具(一)
- 使用JS制作一个鼠标可拖的DIV(三)——移动带图片DIV
- Android 编码规范:(七)避免使用终结方法
- nginx简介--理解nginx配置/模块/openresty
- 【转】Elasticsearch+Django搜索引擎(二)
- 扇贝有道180927每日一句
- Eclipse安装包 百度网盘
- C语言的行指针和列指针
- 计算机网络(第七版)知识点总结第一章——概述
- mysql 监控_【MySQL】MySQL监控工具 mysql-monitor
- 海贼王最新漫画情报分析
- 网页播放器自定义倍速播放
- 网页优化(布局优化、图片优化)
- Android 尺寸转换器(适配各种屏幕)
- 最长递增子序列 O(NlogN)算法
- SVG—初识4之描边动画和路径动画
- 如何用matlab画负倒函数曲线,负倒描述函数
- 课题申报书范文_课题申报书范文.doc