題目:
給你乙個陣列a[1::n],初始時每個元素都為零。對陣列完成一些操作:
第一種可能,給你兩個數p 和x(1<= p <= n),把陣列的第p 個元素替換為x,即a[p] =x.
第二種可能,給你兩個數l 和r(1 <=l <= r <= n),請給出a[l]; a[l + 1]; : : : ; a[r] 這幾個數中去掉乙個最大值和乙個最小值後剩下的數的和是多少.
題解:
單點修改、區間查詢的線段樹可以在o(log n) 的時間內維護區間的和、最大值、最小值.
此題用三個線段樹維護各個區間的和、最大值、最小值,對每個查詢輸出對應區間的sum . max . min 即可.
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
struct node rt[maxn * 4];
int tl(int
x) int
tr(int
x) void pushup(int
x) void build(int
x,int l,int r)
int mid = l + r >> 1;
build(tl(x), l, mid); build(tr(x), mid + 1, r);
pushup(x);
}void upd(int
x, int
pos, ll val)
int mid = rt[x].left + rt[x].right >> 1;
if (pos
<= mid)upd(tl(x), pos, val);
else upd(tr(x), pos, val);
pushup(x);
}ll qury(int
x, int l, int r)
int mid = rt[x].left + rt[x].right >> 1;
if (r <= mid) return qury(tl(x), l, r);
else
if (l > mid) return qury(tr(x), l, r);
else
return qury(tl(x), l, mid) + qury(tr(x), mid + 1, r);
}ll fmin(int
x, int l, int r)
int mid = rt[x].left + rt[x].right >> 1;
ll ret = 0x3fffffffffffff;
if (r <= mid) return min(ret, fmin(tl(x), l, r));
else
if (l > mid) return min(ret, fmin(tr(x), l, r));
else
return min(fmin(tl(x), l, mid), fmin(tr(x), mid + 1, r));
}ll fmax(int
x, int l, int r)
int mid = rt[x].left + rt[x].right >> 1;
ll ret = -0x3ffffffffffffff;
if (r <= mid) return max(ret, fmax(tl(x), l, r));
else
if (l > mid) return max(ret, fmax(tr(x), l, r));
else
return max(fmax(tl(x), l, mid), fmax(tr(x), mid + 1, r));
}int main()
return
0;}
區間插入求和 線段樹入門(二)
題目描述 description 給你n個數,有兩種操作 1 給區間 a,b 的所有數增加x 2 詢問區間 a,b 的數的和。輸入描述 input description 第一行乙個正整數n,接下來n行n個整數,再接下來乙個正整數q,每行表示操作的個數,如果第乙個數是1,後接3個正整數,表示在區間 ...
線段樹 區間求和
給定一數列,規定有兩種操作,一是修改某個元素,二是求區間的連續和。輸入資料第一行包含兩個正整數n,m n 100000,m 500000 以下是m行,每行有三個正整數k,a,b k 0或1,a,b n k 0時表示將a處數字加上b,k 1時表示詢問區間 a,b 內所有數的和。對於每個詢問輸出對應的答...
線段樹(區間更新求和)
poj 3468 include using namespace std define max 100100 struct node 求區間長度 int get dis node tree max 3 long long d max 建樹 long long build int left,int r...