线段树总结 与 模板
2016-10-24 22:50
363 查看
线段树总结 与 模板
单节点更新的 hdu1166 敌兵布阵#include<cstdio> #include<queue> #include<cmath> #include<iostream> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100005; int sum[maxn<<2]; void PushUp(int rt)//单节点更新 求和 求最大 求最小 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt) { if(l==r) { scanf("%d",&sum[rt]);return ; } int m=(l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int p,int add,int l,int r,int rt)//对应的区间[l,r]在线段树中的节点(rt) { if(l==r){ sum[rt]+=add;return ; } int m=(l+r)>>1; if(p<=m) update(p,add,lson); else update(p,add,rson); PushUp(rt);//向上更新父节点 } int query(int L,int R,int l,int r,int rt) { if(L<=l && r<=R) { return sum[rt]; } int m=(l+r)>>1; int ret=0;//求最大或最小时值相应也要修改 if(L<=m) ret+=query(L,R,lson);//这里为什么是加等于 可以直接赋值吧? 这里是两边都要算 下一行是if if(R>m)ret += query(L , R , rson);//这里修改成ret = max or min(ret , query(L , R , lson)); return ret; } int main() { int T , n; scanf("%d",&T); for (int cas = 1 ; cas <= T ; cas ++) { printf("Case %d:\n",cas); scanf("%d",&n); build(1 , n , 1); char op[10]; while (scanf("%s",op)) { if (op[0] == 'E') break; int a,b; scanf("%d%d",&a,&b); if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n ,1));//a是更新的节点 b是增加的值 最左区间 最右区间 根结点 else if (op[0] == 'S') update(a , -b , 1 , n , 1); else update(a , b , 1 , n , 1); } } return 0; }
区间增减 区间求和 最大 或最小 poj3468
#include <cstdio> #include<algorithm> #include<iostream> #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define LL long long #define inf 0x3f3f3f using namespace std; const int maxn = 100005; LL sum[maxn<<2]; LL add[maxn<<2]; void PushDown(int rt,int m)///m是以rt为节点的区间的长度 { if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt];//因为之前是这个增加值没有向下传递 sum[rt<<1] += add[rt] * (m - (m >> 1)); sum[rt<<1|1] += add[rt] * (m >> 1); add[rt] = 0;//表示这个节点没有增加的值 或者说是已经向下传递 } } void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { add[rt] = 0; if (l == r) { scanf("%lld",&sum[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int c,int l,int r,int rt) {//对应的区间[l,r]在线段树中的节点(rt) p是叶子节点[p,p] if (L <= l && r <= R) { add[rt] += c; sum[rt] += (LL)c * (r - l + 1); return ; } PushDown(rt , r - l + 1);//如果没有找到子节点 那么将值向下传递 int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson);//用p 和 区间[l,r]比较 如果l==r 那么就是p原数组的位置 if (m < R) update(L , R , c , rson); PushUp(rt); } LL query(int L,int R,int l,int r,int rt) {//这里是long long 型 要不然会出错 if (L <= l && r <= R) { return sum[rt]; } PushDown(rt,r-l+1);//查询时 也一样 因为update时并不是每个节点都增加的 int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret += query(L , R , lson);//这里为什么是加等于 可以直接赋值吧? if (m<R) ret += query(L , R , rson);//这里修改成ret = max or min(ret , query(L , R , lson)); return ret; } int main() { int n,q,a,b,c;char ch; scanf("%d%d",&n,&q); build(1,n,1); while(q--) { scanf(" %c %d %d",&ch,&a,&b); if(ch=='Q') printf("%d\n",query(a,b,1,n,1)); else { scanf("%d",&c); update(a,b,c,1,n,1); } } return 0; }
区间值设置 区间操作
#include <cstdio>#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
int setv[maxn<<2];
int sum[maxn<<2];
void PushUp(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];//跟上面的一样的思路 模拟一遍有助理解
}
void PushDown(int rt,int m) {
if (setv[rt]) {
setv[rt<<1] = setv[rt];
setv[rt<<1|1] = setv[rt];
sum[rt<<1] = setv[rt] * (m - (m >> 1));
sum[rt<<1|1] = setv[rt] * (m >> 1);
setv[rt] = 0;
}
}
void build(int l,int r,int rt) {
setv[rt] = 0;
sum[rt]=0;
if (l == r) {
sum[rt]=1;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int s,int l,int r,int rt) {
if (L <= l && r <= R) {
setv[rt] = s;
sum[rt] = s * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , s , lson);
if (m < R) update(L , R , s, rson);
PushUp(rt);
}
int query(int l,int r,int rt) {
if (setv[rt] || l==r){
return sum[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
int ret = 0;
ret += query(lson);
ret += query(rson);
return ret;
}
int main() {
int T;scanf("%d",&T);
for(int i=1;i<=T;i++)
{
int N,Q;
scanf("%d%d",&N,&Q);
build(1 , N , 1);
while (Q--)
{
int a,b,s;
scanf("%d%d%d",&a,&b,&s);
update(a,b,s,1,N,1);
}
printf("Case %d: The total value of the hook is %d.\n",i,query(1 , N , 1));
}
return 0;
}
相关文章推荐
- ZKW线段树模板总结
- 线段树 自己总结的模板
- 线段树---分析 &amp;&amp; 模板总结
- 线段树 + 树状数组 【模板总结】
- KPI总结模板:How
- 个人年终总结模板
- KPI总结模板: Why?
- Symbian编程总结-深入篇-瘦模板正解
- 模式总结——模板方法
- 工作总结模板
- [叶伟]KPI总结模板:What(2)
- KPI总结模板:What
- KPI总结模板:How
- [叶伟]KPI总结模板:What(4)
- 线段树的实现(模板)
- [叶伟]KPI总结模板:What(3)
- KPI总结模板:What
- asp下用实现模板加载的的几种方法总结 原创
- KPI总结模板:How
- 项目总结报告模板