您的位置:首页 > 其它

线段树

2015-07-19 16:09 351 查看


线段树

线段树

1.线段树最裸模板
2.线段树区间修改---Lazy大法
3.离散化 + 线段树
4.相关内容
5.由2延伸修改


1.线段树最裸模板

Problem I

[code]#include<iostream>

#include<cstring>

#include<cstdio>

using namespace std;

const int MAX=50010;

#define Lson L,mid,root<<1 //遇到Lson的时候强制替换为后面的语句

#define Rson mid+1,R,root<<1|1

int n,sum[MAX<<2];


void Pushup(int root) //把当前结点的信息更新到父节点

{

sum[root]=sum[root<<1]+sum[root<<1|1];

}


void Build(int L,int R,int root)

{

if(L==R)

{

scanf("%d",&sum[root]);

return ;

}

int mid=(L+R)>>1;

Build(Lson); //左孩子

Build(Rson); //右孩子

Pushup(root);

}


void Update(int q,int val,int L,int R,int root) //在根为root,区间为[L,R]中的线段树修改结点p的值增加val

{

if(L==R)

{

sum[root]+=val;

return ;

}

int mid=(L+R)>>1;

if(q<=mid) Update(q,val,Lson); //说明p在左结点

else Update(q,val,Rson); //说明p在右结点

Pushup(root);

}


int Query(int l, int r, int L, int R, int root)

{

if(l==L && r==R)

return sum[root];


int mid = (L + R) >> 1;

if(r <= mid) return Query(l, r, Lson);

else if(l > mid) return Query(l, r, Rson);

else return Query(l, mid, Lson) + Query(mid+1, r, Rson);

}


int main()

{

int a,b,Case,num=1;

scanf("%d",&Case);

while(Case--)

{

printf("Case %d:\n",num++);

scanf("%d",&n);

Build(1,n,1);

char op[10];

while(scanf("%s",op))

{

if(op[0]=='E') break;

scanf("%d%d",&a,&b);

if(op[0]=='A') Update(a,b,1,n,1);

if(op[0]=='S') Update(a,-b,1,n,1);

if(op[0]=='Q') printf("%d\n",Query(a,b,1,n,1));

}

}

return 0;

}

[/code]


2.线段树区间修改---Lazy大法

Problem II

[code]#include <cstdio>

#include <cstring>


#define maxn 100000 + 10

#define Lson L, mid, rt<<1

#define Rson mid+1, R, rt<<1|1


struct Node

{

int sum, lazy;

} T[maxn<<2];


void PushUp(int rt)

{

T[rt].sum = T[rt<<1].sum + T[rt<<1|1].sum;

}


void PushDown(int L, int R, int rt)

{

int mid = (L + R) >> 1;

T[rt<<1].sum = T[rt].lazy * (mid - L + 1);

T[rt<<1|1].sum = T[rt].lazy * (R - mid);

T[rt<<1].lazy = T[rt].lazy;

T[rt<<1|1].lazy = T[rt].lazy;

T[rt].lazy = 0;

}


void Build(int L, int R, int rt)

{

if(L == R)

{

scanf("%d", &T[rt].sum);

return ;

}

int mid = (L + R) >> 1;

Build(Lson);

Build(Rson);

PushUp(rt);

}


void Update(int l, int r, int v, int L, int R, int rt)

{

if(l==L && r==R)

{

T[rt].lazy = v;

T[rt].sum = v * (R - L + 1);

return ;

}


int mid = (L + R) >> 1;

if(T[rt].lazy) PushDown(L, R, rt);


if(r <= mid) Update(l, r, v, Lson);

else if(l > mid) Update(l, r, v, Rson);

else

{

Update(l, mid, v, Lson);

Update(mid+1, r, v, Rson);

}

PushUp(rt);

}


int Query(int l, int r, int L, int R, int rt)

{

if(l==L && r== R)

return T[rt].sum;


int mid = (L + R) >> 1;

if(T[rt].lazy) PushDown(L, R, rt);


if(r <= mid) return Query(l, r, Lson);

else if(l > mid) return Query(l, r, Rson);

return Query(l, mid, Lson) + Query(mid + 1, r, Rson);

}


int main()

{

int n, q;

scanf("%d", &n);

Build(1, n, 1);

scanf("%d", &q);

int a, b, c, d;

while(q--)

{

scanf("%d%d%d", &a, &b, &c);

if(a)

{

scanf("%d", &d);

Update(b, c, d, 1, n, 1);

}

else printf("%d\n", Query(b, c, 1, n, 1));

}


return 0;

}


[/code]


3.离散化 + 线段树

Problem III

离散型与连续型的区别:

1.叶子节点:在离散型中,叶子节点是[i, i],而连续性中是[i, i + 1];

2.分解区间:在离散型中,一段区间是分解成为[l, m], [m + 1, r],而在连续型中,是分解成为[l, m], [m, r];

3.其他所有类似的判定问题。

[code]#include <iostream>

#include <cstdio>

#include <cstring>

#include <set>

#include <map>


using namespace std;

#define maxn 100005

#define lson L, mid, rt<<1

#define rson mid, R, rt<<1|1


int a[maxn], b[maxn];

int lazy[maxn<<2];

int N, L;

int left_bound = 1, right_bound;


void init()

{

memset(lazy, -1, sizeof(lazy));

right_bound = 0;

}


void read_compress()

{

set<int> s;

for(int i=1; i<=N; i++)

{

scanf("%d%d", &a[i], &b[i]);

s.insert(a[i]);

s.insert(b[i]);

}

map<int, int> m;

for(set<int>::iterator it=s.begin(); it!=s.end(); it++)

m[*it] = ++right_bound;

for(int i=1; i<=N; i++)

{

a[i] = m[a[i]];

b[i] = m[b[i]];

}

}


void pushdown(int L, int R, int rt)

{

if(lazy[rt] >= 0)

lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];

lazy[rt] = -1;

}


void update(int l, int r, int v, int L, int R, int rt)

{

if(l==L && r==R)

{

lazy[rt] = v;

return ;

}

int mid = (L+R)>>1;

if(lazy[rt] >= 0) pushdown(L, R, rt);

if(r <= mid) update(l, r, v, lson);

else if(l >= mid) update(l, r, v, rson);

else

{

update(l, mid, v, lson);

update(mid, r, v, rson);

}

}


void query(int l, int r, int L, int R, int rt, set<int> &s)

{

if(l==L && r==R && lazy[rt]>=0)

{

s.insert(lazy[rt]);

return ;

}

int mid = (L+R)>>1;

if(lazy[rt] >= 0) pushdown(L, R, rt);

if(r <= mid) query(l, r, lson, s);

else if(l >= mid) query(l, r, rson, s);

else

{

query(l, mid, lson, s);

query(mid, r, rson, s);

}

}


int main()

{

while(~scanf("%d%d", &N, &L))

{

init();

read_compress();

int cnt = 0;

for(int i=1; i<=N; i++)

update(a[i], b[i], ++cnt, left_bound, right_bound, 1);


cnt = 0;

    set<int> s;

for(int i=1; i<=N; i++)

query(a[i], b[i], left_bound, right_bound, 1, s);

printf("%d\n", s.size());

}

return 0;

}


[/code]


4.相关内容

The New

Go For it


5.由2延伸修改

线段树区间修改 维护和值、最大值、最小值

[code]#include <cstdio>

#include <cstring>


#define maxn 100000 + 10

#define Lson L, mid, rt<<1

#define Rson mid+1, R, rt<<1|1


int min(int a, int b) {return a<b ? a : b;}

int max(int a, int b) {return a>b ? a : b;}


struct Node

{

int sum, Min, Max, lazy;

} T[maxn<<2];


void PushUp(int rt)

{

T[rt].sum = T[rt<<1].sum + T[rt<<1|1].sum;

T[rt].Min = min(T[rt<<1].Min, T[rt<<1|1].Min);

T[rt].Max = max(T[rt<<1].Max, T[rt<<1|1].Max);

}


void PushDown(int L, int R, int rt)

{

int mid = (L + R) >> 1;

int t = T[rt].lazy;

T[rt<<1].sum = t * (mid - L + 1);

T[rt<<1|1].sum = t * (R - mid);

T[rt<<1].Min = T[rt<<1|1].Min = t;

T[rt<<1].Max = T[rt<<1|1].Max = t;

T[rt<<1].lazy = T[rt<<1|1].lazy = t;

T[rt].lazy = 0;

}


void Build(int L, int R, int rt)

{

if(L == R)

{

scanf("%d", &T[rt].sum);

T[rt].Min = T[rt].Max = T[rt].sum;

return ;

}

int mid = (L + R) >> 1;

Build(Lson);

Build(Rson);

PushUp(rt);

}


void Update(int l, int r, int v, int L, int R, int rt)

{

if(l==L && r==R)//修改区间值

{

T[rt].lazy = v;

T[rt].sum = v * (R - L + 1);

T[rt].Min = T[rt].Max = v;

return ;

}

int mid = (L + R) >> 1;

if(T[rt].lazy) PushDown(L, R, rt);//向下更新一级

if(r <= mid) Update(l, r, v, Lson);

else if(l > mid) Update(l, r, v, Rson);

else

{

Update(l, mid, v, Lson);

Update(mid+1, r, v, Rson);

}

PushUp(rt);

}


int Query(int l, int r, int L, int R, int rt)

{

if(l==L && r== R)

{

printf("(%d, %d)---Min: %d   Max: %d  Sum: %d  \n", L, R, T[rt].Min, T[rt].Max, T[rt].sum);

    return T[rt].sum;

}

int mid = (L + R) >> 1;

if(T[rt].lazy) PushDown(L, R, rt);

if(r <= mid) return Query(l, r, Lson);

else if(l > mid) return Query(l, r, Rson);

return Query(l, mid, Lson) + Query(mid + 1, r, Rson);

}


int main()

{

int n, q;

scanf("%d", &n);

Build(1, n, 1);

scanf("%d", &q);

int a, b, c, d;

while(q--)

{

scanf("%d%d%d", &a, &b, &c);

if(a)

{

scanf("%d", &d);

Update(b, c, d, 1, n, 1);

}

else printf("%d\n", Query(b, c, 1, n, 1));

}

return 0;

}


/*


6

1 2 3 4 5 6

3

0 1 4

1 2 3 0

0 1 4


*/

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: