第一次写线段树题,写的是静态的飘过~~~
线段树:它主要用于处理一段连续区间的插入,查找,统计,查询等操作。
复杂度: 设区间长度是n,所有操作的复杂度是logn级别。
一线段树的建图有两种。
1、最后一层建成线段,就是所有区间都是开区间,最后一层是[1,2] [2,3] [3,4]。。。。。。
2、最后一层建成点,类似[1,1] [2,2]..
二、更新
1、注意更新父节点对子节点的影响。
2、注意更新子节点对父节点的影响。
AC代码:
#include<iostream>
#include<string.h>
#include<algorithm>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y)((x+y)>>1)
using namespace std;
typedef struct str
{
int l;
int r;
int key;
}Node;
Node node[100001*4];
void build(int t,int l,int r)//建树
{
node[t].l=l;node[t].r=r;
node[t].key=1;
if(l==r-1) return;
int mid=MID(l,r);
build(L(t),l,mid);
build(R(t),mid,r);
}
void update(int t,int l,int r,int sum)//更新
{
if(l==node[t].l&&r==node[t].r)
{
node[t].key=sum;
return;
}
if(node[t].key>0)
{
node[L(t)].key=node[t].key;
node[R(t)].key=node[t].key;
node[t].key=-1;
}
int mid=MID(node[t].l,node[t].r);
if(l>=mid) update(R(t),l,r,sum);
else{
if(r<=mid) update(L(t),l,r,sum);
else
{
update(R(t),mid,r,sum);
update(L(t),l,mid,sum);
}
}
}
int Quary(int t,int l,int r)//查找
{
if(node[t].key>0)
return node[t].key*(r-l);
int mid=MID(node[t].l,node[t].r);
return Quary(R(t),mid,r)+Quary(L(t),l,mid);
/*if(l>=mid) return Quary(R(t),l,r);
else
{
if(r<=mid) return Quary(L(t),l,r);
else
{
return Quary(R(t),mid,r)+Quary(L(t),l,mid);
}
}*/
}
int main()
{
int T;
cin>>T;
int tot=0;
while(T--)
{
int n;
cin>>n;
build(1,0,n);
int m;
cin>>m;
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
update(1,x-1,y,z);
}
printf("Case %d: The total value of the hook is %d.\n",++tot,Quary(1,0,n));
}return 0;
}
动态:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct NODE
{
struct NODE *lc,*rc;
int ld,rd;
int key;
NODE()
{
key=1;
}
}*Node,T;
class rmq{
public:
Node root;
rmq()
{
root=new T;
}
~rmq()
{
delete root;
}
Node build(int a,int b);
void update(Node root ,int l,int r,int sum);
int Quary(Node root,int l,int r);
};
Node rmq::build(int a,int b)
{
Node root=new T;
root->ld=a;
root->rd=b;
if(a==b-1) return root;
int mid=(a+b)>>1;
root->lc=build(a,mid);
root->rc=build(mid,b);
return root;
}
void rmq::update(Node root,int l,int r,int sum)
{
if(root->ld==l&&root->rd==r)
{ root->key=sum;
return;
}
if(root->key==sum) return;
if(root->key>0)
{
root->lc->key=root->key;
root->rc->key=root->key;
root->key=-1;
}
int mid=(root->ld+root->rd)>>1;
if(l>=mid) update(root->rc,l,r,sum);
else
{
if(r<=mid) update(root->lc,l,r,sum);
else
{
update(root->lc,l,mid,sum);
update(root->rc,mid,r,sum);
}
}
}
int rmq::Quary(Node root,int l,int r)
{
if(root->key>0)
return root->key*(root->rd-root->ld);
int mid=(root->ld+root->rd)>>1;
return Quary(root->lc,l,mid)+Quary(root->rc,mid,r);
}
int main()
{
int T;
cin>>T;
int tot=0;
while(T--)
{
int n;
cin>>n;
rmq s;
s.root=s.build(0,n);
int m;
cin>>m;
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
s.update(s.root,x-1,y,z);
}
printf("Case %d: The total value of the hook is %d.\n",++tot,s.Quary(s.root,0,n));
}return 0;
}

本文介绍了线段树的数据结构及其在处理连续区间操作的应用,包括两种建树方式、更新及查询操作,并提供了静态和动态线段树的实现代码。
974

被折叠的 条评论
为什么被折叠?



