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 + ; 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的更多相关文章
- [Luogu P4180][BJWC 2010]严格次小生成树
严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...
- luogu P4385 [COCI2009]Dvapravca
传送门 我真的弱,正解都不会还打了个错的暴力 考虑平行线与x轴平行,那么可以按照y为第一关键字升序,x为第二关键字升序排序,然后合法的一段红点就是连续的一段,答案也就是最大的连续红色段 推广到一般情况 ...
- POJ 1703 Find them, Catch them(并查集高级应用)
手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/suncongbo/article/details/76735893 URL: http ...
- [luogu]P1800 software_NOI导刊2010提高(06)[DP][二分答案]
[luogu]P1800 software_NOI导刊2010提高(06) 题目描述 一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块, ...
- Luogu P1801 黑匣子_NOI导刊2010提高(06)
P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个 ...
- 【luogu P1774 最接近神的人_NOI导刊2010提高(02)】 题解
题目链接:https://www.luogu.org/problemnew/show/P1774 归并排序求逆序对. #include <cstdio> #define livelove ...
- 【luogu P1801 黑匣子_NOI导刊2010提高(06)】 题解
题目链接:https://www.luogu.org/problemnew/show/P1801 替罪羊树吼啊! #include <cstdio> #include <cstrin ...
- 【luogu P1807 最长路_NOI导刊2010提高(07)】 题解
题目链接:https://www.luogu.org/problemnew/show/P1807 求最大路?就是把权值取相反数跑最短路. #include <cstdio> #includ ...
- Luogu P1776 宝物筛选_NOI导刊2010提高(02)(多重背包模版)
传送门 多重背包板子题, 多重背包就是每种东西有好几个,可以把它拆分成一个一个的01背包 优化:二进制拆分(拆成1+2+4+8+16+...) 比如18=1+2+4+8+3,可以证明18以内的任何数都 ...
随机推荐
- 解决 The word is not correctly spelled问题
The word is not correctly spelled 此问题是eclipse校验单词拼写造成,如果出在配置文件中,一般会影响到程序的正常执行 解决方法:Window--Preferenc ...
- streamsets 包管理
streamsets 自带一个包管理,可以方便的进行三方组件的添加,比如我们需要处理mongodb 数据,默认是没有添加这个组件的,操作如下: 选择包管理 选择组件 安装 点击安装 提示界面 安装完成 ...
- VMware 11 安装 Mac OS X10.10
一.下载好以下软件--->http://pan.baidu.com/s/1qWDkTbe 1,VMware 11 2,unlocker203(装好VMware11后需要安装补丁unlocker才 ...
- Telnet远程重启路由器TP-LINK
突然断网,以前房东的路由器管理页面可以打开,今天突然间就打不开了.ping了下,可以ping通,于是就想起了房东的路由器是TP-LINK的 可以 telnet登陆的.每次,断网,我都会重启房东的路由器 ...
- Javascript 全局函数是 window 的函数
比如以下函数,看起来不属于任何对象,但它是一个全局对象. 它属于 HTML页面的函数. function myFunction(a, b){ return a * b; } window.myFunc ...
- oracle之 Oracle归档日志管理
在Oracle中,数据一般是存放在数据文件中,不过数据库与Oracle最大的区别之一就是数据库可以在数据出错的时候进行恢复.这个也就是我们常见的Oracle中的重做日志(REDO FILE)的功能了. ...
- POJ3565带权匹配——km算法
题目:http://poj.org/problem?id=3565 神奇结论:当总边权最小时,任意两条边不相交! 转化为求二分图带权最小匹配. 可以用费用流做.但这里学一下km算法. https:// ...
- Form中的keypress事件不能用
Form中的keypress事件不能用 编写人:CC阿爸 2015-4-8 近期在修改系统时,想给一画面增加一个组合键功能,但在form_keypress事件中加入代码,但无论如何也不能触发该动作. ...
- virtualenv基本使用
win 安装 virtualenv pip3 install virtualenv 创建虚拟环境 virtualenv env1 进入虚拟环境 env1/Scripts/activate 退出虚拟环境 ...
- Bootstrap-CL:略缩图
ylbtech-Bootstrap-CL:略缩图 1.返回顶部 1. Bootstrap 缩略图 本章将讲解 Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstr ...