- 著者:zifeiy
- タグ:ツリーライン
HDU1698ジャストフック
- トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=1698
- ツリーラインの特徴:
- 更新:セグメントに更新(クエリ動作が全範囲ため一度だけ含まれ、それがそのまま出力ノード1に可能です)
#include <bits/stdc++.h>
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn = 100010;
int sum[maxn<<2], lazy[maxn<<2];
inline void push_up(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
inline void push_down(int rt, int len) {
if (lazy[rt]) { // 只有在有延迟标记(说明之前全区间覆盖过)才生效
int l_len = len-len/2, r_len = len/2;
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum[rt<<1] = l_len * lazy[rt];
sum[rt<<1|1] = r_len * lazy[rt];
lazy[rt] = 0;
}
}
void build(int l, int r, int rt) {
lazy[rt] = 0;
if (l == r) {
sum[rt] = 1;
return;
}
int m = (l + r) >> 1;
build(lson); build(rson); push_up(rt);
}
void update(int L, int R, int val, int l, int r, int rt) {
if (L <= l && r <= R) {
lazy[rt] = val;
sum[rt] = (r - l + 1) * val;
return;
}
push_down(rt, r-l+1);
int m = (l + r) >> 1;
if (L <= m) update(L, R, val, lson);
if (R > m) update(L, R, val, rson);
push_up(rt);
}
int T, n, m, a, b, c;
int main() {
scanf("%d", &T);
for (int cas = 1; cas <= T; cas ++) {
scanf("%d%d", &n, &m);
build(1, n, 1);
while (m --) {
scanf("%d%d%d", &a, &b, &c);
update(a, b, c, 1, n, 1);
}
printf("Case %d: The total value of the hook is %d.\n", cas, sum[1]);
}
return 0;
}
POJ3468整数でシンプルな問題
- トピックへのリンク:http://poj.org/problem?id=3468
- ツリーラインの特徴:
- 更新:セグメントに更新します。
- クエリ:インターバル合計
#include <cstdio>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn = 100010;
long long sum[maxn<<2], lazy[maxn<<2];
inline void push_up(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
inline void push_down(int rt, int len) {
if (lazy[rt]) {
int l_len = len-len/2, r_len = len/2;
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
sum[rt<<1] += l_len * lazy[rt];
sum[rt<<1|1] += r_len * lazy[rt];
lazy[rt] = 0;
}
}
void build(int l, int r, int rt) {
lazy[rt] = 0;
if (l == r) {
scanf("%lld", &sum[rt]);
return;
}
int m = (l + r) >> 1;
build(lson); build(rson); push_up(rt);
}
void update(int L, int R, long long val, int l, int r, int rt) {
if (L <= l && r <= R) {
lazy[rt] += val;
sum[rt] += (r - l + 1) * val;
return;
}
push_down(rt, r-l+1);
int m = (l + r) >> 1;
if (L <= m) update(L, R, val, lson);
if (R > m) update(L, R, val, rson);
push_up(rt);
}
long long query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return sum[rt];
push_down(rt, r-l+1);
int m = (l + r) >> 1;
long long res = 0;
if (L <= m) res += query(L, R, lson);
if (R > m) res += query(L, R, rson);
return res;
}
int n, q, a, b, c;
char op[2];
int main() {
scanf("%d%d", &n, &q);
build(1, n, 1);
while (q --) {
scanf("%s", op);
if (op[0] == 'C') {
scanf("%d%d%d", &a, &b, &c);
update(a, b, c, 1, n, 1);
} else {
scanf("%d%d", &a, &b);
printf("%lld\n", query(a, b, 1, n, 1));
}
}
return 0;
}
POJ2528市長のポスター
トピックリンク:http://poj.org/problem?id=2528
効果の対象に:あなたは無限に長いボードを与え、その後、順番にn個の高ポスターの上部に取り付けられており、どのように多くのポスターを見ることができ、最後にお聞きします。
アイデアの分析:ツリーライン間隔更新の問題が、気をつけては、直接扱われていないが1E9、セグメントツリー意志は確かにMLE、TLEを維持し、長さに非常に大きくなることが、我々はその点2E4の唯一最大合計ので注意してください我々は前の間隔に離散的なイデオロギーの前処理を使用することができます。
:発生し得るが、以下の2つの簡単な例は、通常の離散欠陥を反映することができなければならない与えられ、単純な離散化誤差に注意を払う
例1:1-10 1-4 5-10
例2:1-10 1-4 6-10
一般的な後離散なっている[1,4][1,2][3,4]
セグメント2を覆って[1,2]
、ライン3つのカバーをアップ[3,4]
?次にセグメント1は、それが完全に上書きされ、
最初の例オフ完全に覆われており、二つの例が覆われていない
二つの隣接点1との間の距離よりも大きい溶液、次いで中間点を挿入し、この質問レイジーマークものアイデア使用して
処理用にマーク最初のセクションを更新しない直接の子ノードを使用すると、下流層を更新する必要がある場合は、マークダウン。
(マークの遅延に格納された値に直接私のコード)を次のようにコードがあります:
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn = 100010;
long long lazy[maxn<<2];
inline void push_down(int rt, int len) {
if (lazy[rt]) {
int l_len = len-len/2, r_len = len/2;
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
lazy[rt] = 0;
}
}
void build(int l, int r, int rt) {
lazy[rt] = 0;
if (l == r) return;
int m = (l + r) >> 1;
build(lson); build(rson);
}
void update(int L, int R, int val, int l, int r, int rt) {
if (L <= l && r <= R) {
lazy[rt] = val;
return;
}
push_down(rt, r-l+1);
int m = (l + r) >> 1;
if (L <= m) update(L, R, val, lson);
if (R > m) update(L, R, val, rson);
}
int ans;
bool vis[maxn];
void query(int l, int r, int rt) {
if (l == r || lazy[rt]) {
if (lazy[rt] && !vis[ lazy[rt] ]) { vis[ lazy[rt] ] = true; ans ++; }
return;
}
int m = (l + r) >> 1;
query(lson); query(rson);
}
int T, n, l[maxn], r[maxn], num[maxn], mp[10000010], sz, cnt;
int main() {
scanf("%d", &T);
while (T --) {
scanf("%d", &n);
cnt = ans = 0;
for (int i = 1; i <= n; i ++) vis[i] = false;
for (int i = 1; i <= n; i ++) {
scanf("%d%d", &l[i], &r[i]);
num[cnt++] = l[i];
num[cnt++] = r[i];
}
sort(num, num+cnt);
cnt = unique(num, num+cnt) - num;
sz = 0;
for (int i = 0; i < cnt; i ++) {
if (i > 0 && num[i-1]+1 < num[i]) mp[ num[i]-1 ] = sz ++;
mp[ num[i] ] = sz ++;
}
build(0, sz-1, 1);
for (int i = 1; i <= n; i ++) {
int lnum = mp[ l[i] ];
int rnum = mp[ r[i] ];
update(lnum, rnum, i, 0, sz-1, 1);
}
query(0, sz-1, 1);
printf("%d\n", ans);
}
return 0;
}
POJ3225範囲
トピックリンク:http://poj.org/problem?id=3225この質問中国の顔の問題。
タイトル効果:操作部、交差点などを補完します。
アイデア:
私たちは操作を分析する必要があります。
- U:間隔\([L、R]は\ ) 1に覆っています。
- I:間隔\(( - \ inftyの、L)\)、\ ((R &LT、+ \ inftyの)\)を0に覆います。
- D:間隔\([L、R] \ ) を0に覆います。
- C:間隔\(( - \ inftyの、L)\)、\ ((R &LT、+ \ inftyの)\)を0に覆い、間隔\([L、R&LT] \) 0/1互換。
- S:間隔\([L、R&LT] \) 0/1入れ替え。
カバーセグメントに操作が非常に簡単で、より特別なもの交換ゾーン0/1この操作であり、我々はXOR演算を呼び出すことができます。
怠惰なタグの場合:
- オーバーレイマーク:我々0又は1が1または0の範囲内に含まれるかどうかを示すために、-1を上記期間は、すなわち1は、0を含ん含ま表します。
- または排他フラグ:XOR演算するかどうか。
自然:範囲は以前にXORは何の意味をマークしていないかどうか、覆われています。
したがって、ノードが空にオーバーレイマーク又はマーカが排他取得する必要があるとき、
及び場合、ノードが排他取得または標識された、最初の文のオーバレイ・マーク、それは0又は1である場合、カバレッジの変化を直接標識、または他の専用タグを変更します。
開区間番号であれば、(たとえエンドポイント間の間隔を表す奇数のためのエンドポイントを示す)扱うことができるように2を乗じて
ツリーラインの特徴:
- 更新:セグメント、セグメントまたはイソブチルへの更新。
- クエリ:シンプルなハッシュ
コード:わずか。