Section 4.4

master
大蒟蒻 9 years ago
parent bb5db70ffd
commit 0050bc4d6a

@ -1,53 +0,0 @@
#include <cstdio>
typedef long long int64;
#define lch(x) ((x) << 1)
#define rch(x) ((x) << 1 | 1)
#define avg(x, y) (((x) + (y)) >> 1)
inline int min(int a, int b)
{
return a < b ? a : b;
}
inline int max(int a, int b) { return a > b ? a : b; }
const int N = 100010;
int64 sum[N << 2], add[N << 2], a[N];
void build(int k, int l, int r)
{
if (l + 1 == r) return void(sum[k] = a[l]);
int m = avg(l, r);
build(lch(k), l, m);
build(rch(k), m, r);
sum[k] += sum[lch(k)] + sum[rch(k)];
}
void modify(int k, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y) return void(add[k] += v);
sum[k] += (min(r, y) - max(l, x)) * v;
int m = avg(l, r);
if (x < m) modify(lch(k), l, m, x, y, v);
if (y > m) modify(rch(k), m, r, x, y, v);
}
int64 query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y) return sum[k] + (r - l) * add[k];
int m = avg(l, r);
return (min(r, y) - max(l, x)) * add[k] +
(x < m ? query(lch(k), l, m, x, y) : 0) +
(y > m ? query(rch(k), m, r, x, y) : 0);
}
int main()
{
int n, m, op1, op2, op3;
char op[2];
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) scanf("%lld", a + i);
build(1, 0, n);
while (m--)
{
scanf("%s%d%d", op, &op1, &op2);
if (op[0] == 'Q')
printf("%lld\n", query(1, 0, n, op1 - 1, op2));
else
scanf("%d", &op3), modify(1, 0, n, op1 - 1, op2, op3);
}
return 0;
}

@ -0,0 +1,70 @@
#include <cctype>
#include <cstdio>
#define C(x) ((x) = getchar())
#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
#define avg(x, y) (((x) + (y)) >> 1)
typedef long long i64;
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
inline void read(int &x)
{
int ch = x = 0, sign = 1;
while (!isdigit(C(ch))) if (ch == '-') sign = -1;
for (; isdigit(ch); C(ch))
x = x * 10 + ch - '0';
x *= sign;
}
const int N = int(1e5 + 5);
i64 add[N << 2], sum[N << 2];
int a[N];
void build(int k, int l, int r)
{
if (l == r - 1) return void(sum[k] = a[l]);
int m = avg(l, r);
build(L(k), l, m);
build(R(k), m, r);
sum[k] = sum[L(k)] + sum[R(k)];
}
void modify(int k, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y)
return void(add[k] += v);
sum[k] += 1ll * (min(r, y) - max(l, x)) * v;
int m = avg(l, r);
if (x < m) modify(L(k), l, m, x, y, v);
if (y > m) modify(R(k), m, r, x, y, v);
}
i64 query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return sum[k] + (r - l) * add[k];
int m = avg(l, r);
i64 res = add[k] * (min(r, y) - max(l, x));
if (x < m) res += query(L(k), l, m, x, y);
if (y > m) res += query(R(k), m, r, x, y);
return res;
}
int main()
{
int n, m;
read(n), read(m);
for (int i = 0; i < n; i++) read(a[i]);
build(1, 0, n);
while (m--)
{
int op = 0, x, y, z;
while (op != 'C' && op != 'Q') C(op);
if (op == 'Q')
{
read(x), read(y);
printf("%lld\n", query(1, 0, n, x - 1, y));
}
else
{
read(x), read(y), read(z);
modify(1, 0, n, x - 1, y, z);
}
}
return 0;
}

@ -0,0 +1,81 @@
#include <cstdio>
#include <cctype>
#define C(x) (x = getchar())
#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
#define avg(x, y) (((x) + (y)) >> 1)
inline void read(int &x)
{
int ch = x = 0, flag = 1;
while (!isdigit(C(ch))) if (ch == '-') flag = -1;
for (; isdigit(ch); C(ch))
x = x * 10 + ch - '0';
x *= flag;
}
const int N = int(1e5 + 5);
typedef long long i64;
int a[N];
i64 A[N << 2], S[N << 2];
inline void add(int k, int l, int r, i64 v)
{
A[k] += v;
S[k] += (r - l) * v;
}
inline void pushdown(int k, int l, int r)
{
if (A[k] == 0) return;
int m = avg(l, r);
add(L(k), l, m, A[k]);
add(R(k), m, r, A[k]);
A[k] = 0;
}
void build(int k, int l, int r)
{
if (l == r - 1) return void(S[k] = a[l]);
int m = avg(l, r);
build(L(k), l, m);
build(R(k), m, r);
S[k] = S[L(k)] + S[R(k)];
}
i64 query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y) return S[k];
pushdown(k, l, r);
int m = avg(l, r);
i64 res = 0;
if (x < m) res += query(L(k), l, m, x, y);
if (y > m) res += query(R(k), m, r, x, y);
return res;
}
void modify(int k, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y) return add(k, l, r, v);
int m = avg(l, r);
pushdown(k, l, r);
if (x < m) modify(L(k), l, m, x, y, v);
if (y > m) modify(R(k), m, r, x, y, v);
S[k] = S[L(k)] + S[R(k)];
}
int main()
{
int n, m;
read(n), read(m);
for (int i = 0; i < n; i++) read(a[i]);
build(1, 0, n);
while (m--)
{
int op = 0, x, y, z;
while (op != 'Q' && op != 'C') C(op);
if (op == 'Q')
{
read(x), read(y);
printf("%lld\n", query(1, 0, n, x - 1, y));
}
else
{
read(x), read(y), read(z);
modify(1, 0, n, x - 1, y, z);
}
}
return 0;
}

@ -0,0 +1,70 @@
#include <cctype>
#include <cstdio>
#define C(x) ((x) = getchar())
#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
#define avg(x, y) (((x) + (y)) >> 1)
typedef long long i64;
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
inline void read(int &x)
{
int ch = x = 0, sign = 1;
while (!isdigit(C(ch))) if (ch == '-') sign = -1;
for (; isdigit(ch); C(ch))
x = x * 10 + ch - '0';
x *= sign;
}
const int N = int(1e5 + 5);
i64 add[N << 2], sum[N << 2];
int a[N];
void build(int k, int l, int r)
{
if (l == r - 1) return void(sum[k] = a[l]);
int m = avg(l, r);
build(L(k), l, m);
build(R(k), m, r);
sum[k] = sum[L(k)] + sum[R(k)];
}
void modify(int k, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y)
return void(add[k] += v);
sum[k] += 1ll * (min(r, y) - max(l, x)) * v;
int m = avg(l, r);
if (x < m) modify(L(k), l, m, x, y, v);
if (y > m) modify(R(k), m, r, x, y, v);
}
i64 query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return sum[k] + (r - l) * add[k];
int m = avg(l, r);
i64 res = add[k] * (min(r, y) - max(l, x));
if (x < m) res += query(L(k), l, m, x, y);
if (y > m) res += query(R(k), m, r, x, y);
return res;
}
int main()
{
int n, m;
read(n), read(m);
for (int i = 0; i < n; i++) read(a[i]);
build(1, 0, n);
while (m--)
{
int op = 0, x, y, z;
while (op != 'C' && op != 'Q') C(op);
if (op == 'Q')
{
read(x), read(y);
printf("%lld\n", query(1, 0, n, x - 1, y));
}
else
{
read(x), read(y), read(z);
modify(1, 0, n, x - 1, y, z);
}
}
return 0;
}

@ -0,0 +1,15 @@
struct node
{
int val, dis;
node *ch[2];
};
#define dis(x) ((x) ? (x)->dis : -1)
node *merge(node *a, node *b)
{
if (a && b) return (node*)(uintptr_t(a) | uintptr_t(b));
if (a->val < b->val) swap(a, b);
a->ch[1] = merge(a->ch[1], b);
if (dis(a->ch[0]) < dis(a->ch[1])) swap(a->ch[0], a->ch[1]);
a->dis = dis(a->ch[1]) + 1;
return a;
}

@ -0,0 +1,81 @@
#include <cstdio>
#include <cctype>
#define C(x) (x = getchar())
#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
#define avg(x, y) (((x) + (y)) >> 1)
inline void read(int &x)
{
int ch = x = 0, flag = 1;
while (!isdigit(C(ch))) if (ch == '-') flag = -1;
for (; isdigit(ch); C(ch))
x = x * 10 + ch - '0';
x *= flag;
}
const int N = int(1e5 + 5);
typedef long long i64;
int a[N];
i64 A[N << 2], S[N << 2];
inline void add(int k, int l, int r, i64 v)
{
A[k] += v;
S[k] += (r - l) * v;
}
inline void pushdown(int k, int l, int r)
{
if (A[k] == 0) return;
int m = avg(l, r);
add(L(k), l, m, A[k]);
add(R(k), m, r, A[k]);
A[k] = 0;
}
void build(int k, int l, int r)
{
if (l == r - 1) return void(S[k] = a[l]);
int m = avg(l, r);
build(L(k), l, m);
build(R(k), m, r);
S[k] = S[L(k)] + S[R(k)];
}
i64 query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y) return S[k];
pushdown(k, l, r);
int m = avg(l, r);
i64 res = 0;
if (x < m) res += query(L(k), l, m, x, y);
if (y > m) res += query(R(k), m, r, x, y);
return res;
}
void modify(int k, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y) return add(k, l, r, v);
int m = avg(l, r);
pushdown(k, l, r);
if (x < m) modify(L(k), l, m, x, y, v);
if (y > m) modify(R(k), m, r, x, y, v);
S[k] = S[L(k)] + S[R(k)];
}
int main()
{
int n, m;
read(n), read(m);
for (int i = 0; i < n; i++) read(a[i]);
build(1, 0, n);
while (m--)
{
int op = 0, x, y, z;
while (op != 'Q' && op != 'C') C(op);
if (op == 'Q')
{
read(x), read(y);
printf("%lld\n", query(1, 0, n, x - 1, y));
}
else
{
read(x), read(y), read(z);
modify(1, 0, n, x - 1, y, z);
}
}
return 0;
}

@ -372,6 +372,7 @@ Manacher 模板题
\paragraph{左偏树的操作}
\subparagraph{合并}
现在我们有两棵左偏树A和B欲将其合并。我们假设A的根节点大于B的根节点不然交换一下就行了。然后把A的右子节点与树B合并作为A的新右子节点检查A现在的左子节点和右子节点的距离如果右子节点的距离大于左子节点那么交换这两棵子树然后更新A的距离如此这般递归下去因为只有$\log_2{n}$的深度,所以铁定不会爆栈,除非你的脸黑到一定境界了。
\codeinput[合并的简单实现]{assets/day4/merge_impl.cpp}
\subparagraph{插入} 把新节点当作一棵只有一个节点的树与原树合并。
\subparagraph{删除极值} 合并根节点下的两个子节点。
\subparagraph{删除指定元素} 将指定节点的两个子树合并作为这个节点。然后维护其父节点的数值,如果父节点被改变,就继续向上维护,直到节点数据不改变。
@ -379,4 +380,17 @@ Manacher 模板题
\subparagraph{\href{http://www.lydsy.com/JudgeOnline/problem.php?id=2809}{BZOJ2809} - [Apio2012]dispatching}
考虑对每个点维护一个大根堆,堆内存储的是这个节点子树内所有点的$C_i$。当堆内的和大于$M$时就要弹出堆顶元素;每个点的堆可以通过将所有儿子的堆合并起来再插入自己节点的$C_i$来得到
\codeinput[Apio2012 dispatching]{assets/day4/bzoj2809.cpp}
\subsection{线段树} 既可以$\log(n)$修改,也可以$\log(n)$查询最值,也可以$\log(n)$查询和,总之只要是能合并的数据都能在$\log(n)$的时间内用其维护。
\paragraph{普通的线段树:单点修改,区间查询} 直接搞
\paragraph{稍屌的线段树:区间修改,单点查询} 普通的Lazy-tag
\paragraph{通用的线段树:区间修改,区间查询}
这东西包括以上两者,有两种实现方法,标记下传和标记永久化,其中标记永久化在可持久化数据结构中是必须的。现在给出一个大模板题,并且下面将会用两种方法加以实现。\\
这是题:\href{http://poj.org/problem?id=3468}{POJ3468} - A Simple Problem with Integers
\subparagraph{标记下传}
这玩意儿是这么个搞法,还是照例的打标记,当我们要从某个节点递归下去时,将当前节点的$add$值下传,更新两个子节点的$add$$sum$值,并将当前节点的$add$值清零。
\codeinput[标记下传例程2.3s]{assets/day4/poj3468_pushdown.cpp}
\subparagraph{标记永久化}
这种情况下$add$标记将不会被下传,子节点的影响在修改时便已计算,递归时要累加祖先节点上的标记。
\codeinput[标记永久化例程2.0s]{assets/day4/3468_persistentTag.cpp}
经过测试发现标记永久化的写法快一些可能是因为没有那么多的pushdown导致的。
\end{document}
Loading…
Cancel
Save