1.概述
线段树,也叫区间树,是一棵平衡二叉树。它在每个节点保存一条线段,通常用于解决数列维护问题,基本能够保证每个操作的时间复杂度为O(logn)。
2.线段树的操作一般包括:单点更新、成段更新、区间合并、扫描线等......(这次先写一点吧):
单点更新:
hdu1754点击打开链接
代码如下:
#include<iostream>
#include<cstdio>
#define MID(x,y) ((x+y)>>1)
#define l(t) t<<1
#define r(t) t<<1|1
#define INF 900000
int ans;
struct Node
{
int l;
int r;
int max;
}tree[INF];
void push_up(int t)
{
tree[t].max=tree[l(t)].max>tree[r(t)].max?tree[l(t)].max:tree[r(t)].max;
}
void build_tree(int l,int r,int t)
{
tree[t].l=l; tree[t].r=r;
if(l==r)
{
scanf("%d",&tree[t].max);
return;
}
int mid=MID(l,r);
build_tree(l,mid,l(t));
build_tree(mid+1,r,r(t));
push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].max=num;
return;
}
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) Update_tree(l,r,l(t),num);
else if(l>mid) Update_tree(l,r,r(t),num);
else
{
Update_tree(l,mid,l(t),num);
Update_tree(mid+1,r,r(t),num);
}
push_up(t);
}
void query_tree(int l,int r,int t)
{
if(l==tree[t].l && tree[t].r==r)
{
ans=ans>tree[t].max?ans:tree[t].max;
return;
}
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) query_tree(l,r,l(t));
else if(l>mid) query_tree(l,r,r(t));
else
{
query_tree(l,mid,l(t));
query_tree(mid+1,r,r(t));
}
}
int main()
{
int m,n,a,b;
while(~scanf("%d%d",&n,&m))
{
build_tree(1,n,1);
while(m--)
{
char c[5];
scanf("%s%d%d",c,&a,&b);
if(c[0]=='U')
Update_tree(a,a,1,b);
else
{
ans=0;
query_tree(a,b,1);
printf("%d\n",ans);
}
}
}
return 0;
}
hdu1394点击打开链接
代码如下:
#include<iostream>
#include<cstdio>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 100000
int sum;
struct Node
{
int l,r;
int sum;
}tree[INF];
void push_up(int t)
{
tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void build_tree(int l,int r,int t)
{
tree[t].l=l; tree[t].r=r; tree[t].sum=0;
if(l==r) return;
int mid=MID(l,r);
build_tree(l,mid,l(t));
build_tree(mid+1,r,r(t));
}
void Update_tree(int l,int r,int t)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].sum=1;
return;
}
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) Update_tree(l,r,l(t));
else if(l>mid) Update_tree(l,r,r(t));
else
{
Update_tree(l,mid,l(t));
Update_tree(mid+1,r,r(t));
}
push_up(t);
}
void query_tree(int l,int r,int t)
{
if(tree[t].l==l && tree[t].r==r)
{
sum+=tree[t].sum; return;
}
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) query_tree(l,r,l(t));
else if(l>mid) query_tree(l,r,r(t));
else
{
query_tree(l,mid,l(t));
query_tree(mid+1,r,r(t));
}
}
int main()
{
int n;
int a[5005];
while(~scanf("%d",&n))
{
build_tree(1,n,1);
sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]++;
if(a[i]+1<=n)
query_tree(a[i]+1,n,1);
Update_tree(a[i],a[i],1);
}
int ans=sum;
for(int i=0;i<n;i++)
{
sum=sum+(n-a[i])-(a[i]-1);
if(ans>sum) ans=sum;
}
printf("%d\n",ans);
}
return 0;
}
成段更新:(需要用到延迟标记)
hdu1698点击打开链接
代码如下:
#include<iostream>
#include<cstdio>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 400000
using namespace std;
struct Node
{
int l;
int r;
int flag;
int sum;
}tree[INF];
void push_up(int t)
{
tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void push_down(int t,int len)
{
if(tree[t].flag)
{
tree[l(t)].flag=tree[r(t)].flag=tree[t].flag;
tree[l(t)].sum=tree[t].flag*(len-(len>>1));
tree[r(t)].sum=tree[t].flag*(len>>1);
tree[t].flag=0;
}
}
void build_tree(int l,int r,int t)
{
tree[t].l=l; tree[t].r=r; tree[t].flag=0;
if(l==r)
{
tree[t].sum=1; return;
}
int mid=MID(l,r);
build_tree(l,mid,l(t));
build_tree(mid+1,r,r(t));
push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].flag=num;
tree[t].sum=(r-l+1)*num;
return;
}
push_down(t,tree[t].r-tree[t].l+1);
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) Update_tree(l,r,l(t),num);
else if(l>mid) Update_tree(l,r,r(t),num);
else
{
Update_tree(l,mid,l(t),num);
Update_tree(mid+1,r,r(t),num);
}
push_up(t);
}
int main()
{
int t,count=1;
cin>>t;
while(t--)
{
int n,m,a,b,c;
scanf("%d%d",&n,&m);
build_tree(1,n,1);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
Update_tree(a,b,1,c);
}
printf("Case %d: The total value of the hook is %d.\n",count++,tree[1].sum);
}
return 0;
}
POJ3468 点击打开链接
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define l(t) t<<1
#define r(t) t<<1|1
#define MID(x,y) ((x+y)>>1)
#define INF 400000
#define ll long long
ll sum,c;
struct Node
{
int l;
int r;
ll sum;
ll flag;
}tree[INF];
void push_up(int t)
{
tree[t].sum=tree[l(t)].sum+tree[r(t)].sum;
}
void push_down(int t,int num)
{
if(tree[t].flag)
{
tree[l(t)].flag+=tree[t].flag;
tree[r(t)].flag+=tree[t].flag;
tree[l(t)].sum+=tree[t].flag*(num-(num>>1));
tree[r(t)].sum+=tree[t].flag*(num>>1);
tree[t].flag=0;
}
}
void build_tree(int l,int r,int t)
{
tree[t].l=l; tree[t].r=r; tree[t].flag=0;
if(l==r)
{
scanf("%lld",&tree[t].sum);
return;
}
int mid=MID(l,r);
build_tree(l,mid,l(t));
build_tree(mid+1,r,r(t));
push_up(t);
}
void Update_tree(int l,int r,int t,int num)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].flag+=num;
tree[t].sum+=num*(r-l+1);
return ;
}
push_down(t,tree[t].r-tree[t].l+1);
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) Update_tree(l,r,l(t),num);
else if(l>mid) Update_tree(l,r,r(t),num);
else
{
Update_tree(l,mid,l(t),num);
Update_tree(mid+1,r,r(t),num);
}
push_up(t);
}
void query_tree(int l,int r,int t)
{
if(tree[t].l==l && tree[t].r==r)
{
sum+=tree[t].sum;
return ;
}
push_down(t,tree[t].r-tree[t].l+1);
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) query_tree(l,r,l(t));
else if(l>mid) query_tree(l,r,r(t));
else
{
query_tree(l,mid,l(t));
query_tree(mid+1,r,r(t));
}
}
int main()
{
int n,q,a,b;
//ll c;
char str[5];
while(~scanf("%d%d",&n,&q))
{
build_tree(1,n,1);
while(q--)
{
scanf("%s",str);
if(str[0]=='Q')
{
sum=0;
scanf("%d%d",&a,&b);
query_tree(a,b,1);
printf("%lld\n",sum);
}
else
{
scanf("%d%d%lld",&a,&b,&c);
Update_tree(a,b,1,c);
}
}
}
return 0;
}
POJ2528 点击打开链接
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define l(t) (t<<1)
#define r(t) (t<<1|1)
#define MID(x,y) ((x+y)>>1)
#define INF 20010
using namespace std;
int result[INF],visit[INF];
int ncase,cnt,n;
struct Node
{
int l,r;
int color;
}tree[INF*4];
struct _node
{
int id;
int num;
}Max[INF];
bool cmp(_node a,_node b)
{
return a.num<b.num;
}
int discretize()
{
cin>>n;
for(int i=0;i<n*2;i++)
{
scanf("%d",&Max[i].num);
Max[i].id=i;
}
sort(Max,Max+n*2,cmp);
int j=0;
for(int i=0;i<n*2;i++)
{
if(i==0 || Max[i].num!=Max[i-1].num) result[Max[i].id]=++j;
else result[Max[i].id]=j;
}
return result[Max[n*2-1].id];
}
void push_down(int t)
{
if(tree[t].color)
{
tree[l(t)].color=tree[r(t)].color=tree[t].color;
tree[t].color=0;
}
}
void build_tree(int l,int r,int t)
{
tree[t].l=l; tree[t].r=r; tree[t].color=0;
if(l==r) return;
int mid=MID(l,r);
build_tree(l,mid,l(t));
build_tree(mid+1,r,r(t));
}
void Update_tree(int l,int r,int t,int color)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].color=color;
return;
}
push_down(t);
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) Update_tree(l,r,l(t),color);
else if(l>mid) Update_tree(l,r,r(t),color);
else
{
Update_tree(l,mid,l(t),color);
Update_tree(mid+1,r,r(t),color);
}
}
void query_tree(int l,int r,int t)
{
if(tree[t].color)
{
if(!visit[tree[t].color]) {cnt++;visit[tree[t].color]=1;}
return;
}
int mid=MID(tree[t].l,tree[t].r);
if(r<=mid) query_tree(l,r,l(t));
else if(l>mid) query_tree(l,r,r(t));
else
{
query_tree(l,mid,l(t));
query_tree(mid+1,r,r(t));
}
return;
}
int main()
{
cin>>ncase;
while(ncase--)
{
int k=discretize();
build_tree(1,k,1);
int color=0;
for(int i=0;i<n*2;i+=2)
{
color++;
Update_tree(result[i],result[i+1],1,color);
}
memset(visit,0,sizeof(visit));
cnt=0;
query_tree(1,k,1);
printf("%d\n",cnt);
}
return 0;
}
未完待续。。。