您的位置:首页 > 其它

线段树的各种板子

2016-12-17 18:19 387 查看

很明显不是刚刚写的线段树

线段树是什么呢?

线段树啊…

大概就是一颗可爱的二叉树…

它的每一个节点代表着一个区间的一个性质…

(比如说最大值最小值还有和之类的…)

然后因为是二叉树所以有很多奇奇怪怪的东西都来了…

至于有什么也不打算细讲。

一个点x的左儿子就是x*2呀,右儿子就是x*2+1呀

还有在线段树里面

叶儿子

或者说叶节点 所代表的区间是1呀。

想象成初中历史书上的周朝等级制度图就吼了呀!



只不过是一颗树而已。

或者这么看更吼?



反正就是一颗树辣!不是一颗赛艇!

我承认走神了(义正言辞)。

真正的线段树是这样的。。。



大概就是这样!

然后上强势板子!

1.单点修改+区间求和!

#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    <algorithm>
#define ls (x << 1)
#define rs (x << 1 | 1)
#define MID int mid=(l+r)>>1
using namespace std;
int a[101000],t[400100],n,m,L,R,place,add,Ans;
inline int gi()
{
int x=0,si=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')si=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
return x*si;
}
inline void build(int x,int l,int r)
{
if(l^r){MID;build(ls,l,mid);build(rs,mid+1,r);t[x]=t[ls]+t[rs];}
else t[x]=a[l];
return;
}
inline void updata(int x,int l,int r,int k,int addnum)
{
if(l^r)
{
MID;
if(k<=mid)updata(ls,l,mid,k,addnum);
else updata(rs,mid+1,r,k,addnum);
t[x]=t[ls]+t[rs];
}
else t[x]+=addnum;
return;
}
inline int query(int x,int l,int r,int xl,int xr)
{
if(l^xl || r^xr)
{
MID;
if(mid<xl)return query(rs,mid+1,r,xl,xr);
else if(mid>=xr)return query(ls,l,mid,xl,xr);
else return query(ls,l,mid,xl,mid)+query(rs,mid+1,r,mid+1,xr);
}
else return t[x];
}
int main()
{
n=gi();
for(int i=1;i<=n;++i)a[i]=gi();
build(1,1,n);m=gi();
while(m--)
{
int type=gi();
if(type==1)
{
place=gi();add=gi();
updata(1,1,n,place,add);
}
else
{
L=gi();R=gi();
printf("%d\n",query(1,1,n,L,R));
}
}
}


然后是区间修改+看你看不看得出来的查询!

你问我lazy和down是什么意思?因为很懒!懒得改!

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 500010
#define ls x << 1
#define rs x << 1 | 1
using namespace std;
int sum
, lazy
, n, q, i, size
, a
;
int gi() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
void down(int x) {
sum[ls] += lazy[x] * size[ls];
sum[rs] += lazy[x] * size[rs];
lazy[ls] += lazy[x], lazy[rs] += lazy[x], lazy[x] = 0;
}
void build(int x, int l, int r) {
size[x] = (r - l + 1);
if (l == r) {sum[x] = a[l]; return;}
int mid = (l + r) >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
sum[x] = sum[ls] + sum[rs];
}
void updata(int x, int l, int r, int xl, int xr, int v) {
down(x);
if (xl == l && xr == r) {
sum[x] += v * size[x], lazy[x] += v;
return;
}
int mid =(l + r) >> 1;
if (xr <= mid) updata(ls, l, mid, xl, xr, v);
else if (xl > mid) updata(rs, mid + 1, r, xl, xr, v);
else updata(ls, l, mid, xl, mid, v), updata(rs, mid + 1, r, mid + 1, xr, v);
sum[x] = sum[ls] + sum[rs];
}

int query(int x, int l, int r, int xl, int xr) {
down(x);
if (xl <= l && r <= xr) return sum[x];
int mid = (l + r) >> 1;
if (xr <= mid) return query(ls, l, mid, xl, xr);
else if (xl > mid) return query(rs, mid + 1, r, xl, xr);
else return query(ls, l, mid, xl, mid) + query(rs, mid + 1, r, mid + 1, xr);
}
int main() {
n = gi();
for (i = 1; i <= n; i++) a[i] = gi();
q = gi();
build(1, 1, n);
for (i = 1; i <= q; i++) {
int v, l, r, type;                                              //type=1:add      type!=1:find sum
scanf("%d", &type);
if (type == 1) scanf("%d%d%d", &l, &r, &v), updata(1, 1, n, l, r, v);
else scanf("%d%d", &l,&r), printf("%d\n", query(1, 1, n, l, r));
}
}


然后还有什么不懂得朋友可以

点一波关注再留言

嘿嘿嘿。

这个时候是不是应该

日常安利一波

小题目?

codevs 1080 绝对不是什么裸题

codevs 1082 也不是什么裸题

然后大家可能会发现好难呀

给大家一道裸题吧!

codevs 1954 ( 题目名字就叫线段树 )

啦啦啦啦!

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