线段树
Feature
Segment tree is derived from the RMQ question, which use segment tree to speed up the updating sparse table process.
RMQ
Definition: range minimum query.
Solution: let \(d(i, j)\) to be the minimum value of \([i..i+2^{j}-1]\) \(d(i, j)= min(d(i, j-1), d(i+2^{j-1},j-1))\), let \(k\) be the max integar satisfy the constrain, \(2^k\leq R-L+1\)
Code can be devided into two parts:
void RMQ_Init(const vector<int> &A)
{
int n= A.size();
for (int i= 0; i< n; ++i){
d[i][0]= A[i];
}
for (int j= 1; j< n; ++j){
for (int i= 0; i+(1<<j)-1< n; ++j){
d[i][j]= min(d[i][j-1], d[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ(int L, int R)
{
int k= 0;
while ((1<<(k+1)) < R-L){
++k;
}
return min(d[L][k], d[R-(1<<k)+1][k]);
}
Segment Tree 1: Point Correcting
Segment Tree 2: Interval Correction
There are two different operation determine that two kinds of interval correction.
Code 1 support these two operations:
- \(Add(L, R, v)\), elements in interval\([L..R]\) all plus \(v\)
- \(Query(L, R)\), calculate the sum, the max number, the min number of \([L..R]\)
/*y1, y2 are the lower bound and upper bound of the interval we do query operation, v is the number that the array is going to plus*/
void Maintain(int o, int L, int R)
{
int lc= o*2, rc= o*2+1;
sumv[o]= minv[o]= maxv[o]= 0;
if (R> L){
sumv[o]= sumv[lc]+sumv[rc];
minv[o]= min(minv[lc], minv[rc]);
maxv[o]= max(maxv[lc], maxv[rc]);
}
minv[o]+= addv[o];
maxv[o]+= addv[o];
sumv[o]+= addv[o]*(R-L+1);
}
void Update(int o, int L, int R)
{
int lc= o*2, rc= o*2+1;
if (y1<= L && y2>= R){
addv[o]+= v;
}
else{
int M= L+(R-L)/2;
if (y1<= M){
Update(lc, L, M);
}
if (y2> M){
Update(rc, M+1, R);
}
}
Maintain(o, L, R);
}
int global_min, global_max, global_sum;
void Query(int o, int L, int R, int add)
{
if (y1<= L && y2>= R){
global_sum+= sumv[o]+add*(R-L+1)
global_max= max(global_max, maxv[o]+add);
global_min= min(global_min, minv[o]+add);
}
else{
int M= L+(R-L)/2;
if (y1<= M){
Query(o*2, L, M, add+addv[o]);
}
if (y2> M){
Query(o*2+1, L, M, add+addv[o]);
}
}
}
Code21 support these two operations:
- \(Set(L, R, v)\), elements in interval \([L..R]\) are set by v
- \(Query(L, R)\), calculate the sum, the max number, the min number of \([L..R]\)
void Maintain(int o, int L, int R)
{
int lc= o*2, rc= o*2+1;
if (setv[o]>= 0){
sumv[o]= setv[o]*(R-L+1);
minv[o]= setv[o];
maxv[o]= setv[o];
}
else if (R> L){
sumv[o]= sumv[lc]+sumv[rc];
minv[o]= min(minv[lc], minv[rc]);
maxv[o]= max(maxv[lc], maxv[rc]);
}
}
void Update(int o, int L, int R)
{
int lc= o*2, rc= o*2+1;
if (y1<= L && y2>= R){
setv[o]=v;
}
else{
Pushdown(o);
int M= L+(R-L)/2;
if (y1<= M){
Update(lc, L, M);
}
else{
Maintain(lc, L, M);
}
if (y2> M){
Update(rc, M+1, R);
}
else{
Maintain(rc, M+1, R);
}
}
Maintain(o, L, R);
}
void Pushdown(int o)
{
int lc= o*2, rc= o*2+1;
if (setv[o]>= 0){
setv[lc]= setv[rc]= setv[o];
set[o]= -1;
}
}
void Query(int o, int L, int R)
{
if (setv[o]>= 0){
global_sum+= setv[o]*(min(R, y2)-max(L, y1)+1);
global_min= min(global_min, setv[o]);
global_max= max(global_max, setv[o]);
}
else if (y1<= L && y2>= R){
global_sum+= sumv[o];
global_min= min(global_min, minv[o]);
global_max= max(global_max, maxv[o]);
}
else{
int M= L+(R-L)/2;
if (y1<= M){
Query(o*2, L, M);
}
if (y2> M){
Query(o*2+1, M+1, R);
}
}
}
OJ Practise
POJ 1177 & HDOJ 1828
I don't know the fxxking reason why "c++ compiler" can "AC", but "g++ compiler" just fxxking show me "Runtime Error".
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int OUT= -1;
const int IN= 1;
const int NO= 0;
const int OL= 1;
const int INF= 0x7fffffff;
const int maxx= 20000+10;
int egl, egr;
struct Segment{
int x;
int yl, yh;
int oi;
Segment(){};
Segment(int xx, int yyl, int yyh, int ooi) : x(xx), yl(yyl), yh(yyh), oi(ooi){}
bool operator <(const Segment &a) const
{
return x< a.x || (x== a.x && oi== IN);
}
}dt[maxx];
struct SegmentTNode{
int l, r;
int cov;
int len;
int nd;
int lop, rop;
SegmentTNode(){};
SegmentTNode(int ll, int rr) : l(ll), r(rr)
{
cov= len= nd= lop= rop= 0;
}
}SegTr[maxx<<2];
inline int LeftChild(int k)
{
return k<<1;
}
inline int RightChild(int k)
{
return ((k<<1)|1);
}
inline int Mid(int k)
{
return (SegTr[k].l+SegTr[k].r)>>1;
}
void Build(int o, int L, int R)
{
SegTr[o]= SegmentTNode(L, R);
if (L== R){
return;
}
int mid= Mid(o);
Build(LeftChild(o), L, mid);
Build(RightChild(o), mid+1, R);
}
void Maintain(int o)
{
if (SegTr[o].cov){
SegTr[o].len= SegTr[o].r-SegTr[o].l +1;
SegTr[o].rop= SegTr[o].lop= SegTr[o].nd= 1;
}
else if (SegTr[o].l== SegTr[o].r){
SegTr[o].lop=SegTr[o].rop= SegTr[o].nd= SegTr[o].len= 0;
}
else{
int lc= LeftChild(o);
int rc= RightChild(o);
SegTr[o].len= SegTr[lc].len+ SegTr[rc].len;
if (OL== SegTr[lc].rop && OL== SegTr[rc].lop){
SegTr[o].nd= SegTr[lc].nd+ SegTr[rc].nd-1;
}
else{
SegTr[o].nd= SegTr[lc].nd+ SegTr[rc].nd;
}
SegTr[o].rop= SegTr[rc].rop;
SegTr[o].lop= SegTr[lc].lop;
}
}
void Update(int o, int st)
{
if (egl<= SegTr[o].l && SegTr[o].r<= egr){
SegTr[o].cov+= st;
}
else{
int mid= Mid(o);
if (egl<= mid){
Update(LeftChild(o), st);
}
if (egr> mid){
Update(RightChild(o), st);
}
}
Maintain(o);
}
int main()
{
int n, m, lb, ub, ans;
while (EOF!= scanf("%d", &n)){
ans= m= 0;
lb= INF;
ub= -INF;
for (int xl, xr, yl, yh, i= 0; i< n; ++i){
scanf("%d %d %d %d", &xl, &yl, &xr, &yh);
lb= min(lb, yl);
ub= max(ub, yh);
dt[m++]= Segment(xl, yl, yh, IN);
dt[m++]= Segment(xr, yl, yh, OUT);
}
Build(1, lb, ub-1);
sort(dt, dt+m);
for (int i= 0; i< m; ++i){
int tmp= SegTr[1].len;
if (0!= i){
ans+= 2*(SegTr[1].nd)*(dt[i].x-dt[i-1].x);
}
egl= dt[i].yl;
egr= dt[i].yh-1;
Update(1, dt[i].oi);
ans+= abs(SegTr[1].len-tmp);
}
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号