线段树的各种板子
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 ( 题目名字就叫线段树 )