xtu oj 1238 线段树
来源:互联网 发布:电脑3.0端口怎么设置 编辑:程序博客网 时间:2024/06/05 14:45
做了我好长时间啊,这个线段树还是很经典的
题意:
四种操作,题目写的很清楚,就不说了,主要是这个题目对于操作2 3 用lazy标记很巧妙
题解:
线段树,lazy标记升级
void pushDown(int p){ if(lazy[p]) { lazy[p<<1]+=lazy[p]; lazy[p<<1|1]+=lazy[p]; sum[p<<1]+=lazy[p]; sum[p<<1|1]+=lazy[p]; mins[p<<1]+=lazy[p]; mins[p<<1|1]+=lazy[p]; lazy[p]=0; } sum[p<<1|1]=min(sum[p<<1|1],sum[p]); sum[p<<1|1]=max(sum[p<<1|1],mins[p]); mins[p<<1|1]=max(mins[p<<1|1],mins[p]); mins[p<<1|1]=min(mins[p<<1|1],sum[p]); sum[p<<1]=min(sum[p<<1],sum[p]); sum[p<<1]=max(sum[p<<1],mins[p]); mins[p<<1]=max(mins[p<<1],mins[p]); mins[p<<1]=min(mins[p<<1],sum[p]);}
后面的那8个式子子,是向下传递最大最小值
若父亲节点的最大值是max 最小值是min,那么子节点的最大最小值一定在min~max范围内
比如说:子节点的最小值要么等于min,要么大于min,若大于min的时候就要注意了,不能大于父亲节点的最大值
满足这些条件就可以得到一个完美的lazy标记的pushDown函数了
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define MAXN 200010#define lson l,mid,p<<1#define rson mid+1,r,p<<1|1#define mem(a) memset(a,0,sizeof(a[0]))#define LL long longLL min(LL x,LL y){return x<y?x:y;}LL max(LL x,LL y){return x>y?x:y;}LL sum[MAXN<<2];LL mins[MAXN<<2];LL lazy[MAXN<<2];void pushUp(int p){ sum[p]=max(sum[p<<1],sum[p<<1|1]); mins[p]=min(mins[p<<1],mins[p<<1|1]);}void pushDown(int p){ if(lazy[p]) { lazy[p<<1]+=lazy[p]; lazy[p<<1|1]+=lazy[p]; sum[p<<1]+=lazy[p]; sum[p<<1|1]+=lazy[p]; mins[p<<1]+=lazy[p]; mins[p<<1|1]+=lazy[p]; lazy[p]=0; } sum[p<<1|1]=min(sum[p<<1|1],sum[p]); sum[p<<1|1]=max(sum[p<<1|1],mins[p]); mins[p<<1|1]=max(mins[p<<1|1],mins[p]); mins[p<<1|1]=min(mins[p<<1|1],sum[p]); sum[p<<1]=min(sum[p<<1],sum[p]); sum[p<<1]=max(sum[p<<1],mins[p]); mins[p<<1]=max(mins[p<<1],mins[p]); mins[p<<1]=min(mins[p<<1],sum[p]);}void build(int l,int r,int p){ lazy[p]=0;///重要,不知道memset和这个有什么区别 if(l==r){ scanf("%I64d",&sum[p]); mins[p]=sum[p]; return; } int mid=(l+r)>>1; build(lson); build(rson); pushUp(p);}LL ans_max,ans_min;void query(int l,int r,int p,LL i,LL j){ if(l>=i&&r<=j){ ans_max=max(ans_max,sum[p]); ans_min=min(ans_min,mins[p]); return ; } pushDown(p);///防止有值没有传下去 int mid=(l+r)>>1; if(mid>=i) query(lson,i,j); if(mid<j) query(rson,i,j); pushUp(p);}void update_1(int l,int r,int p,LL i,LL j,LL num){ if(l>=i&&r<=j){ sum[p]+=num; mins[p]+=num; lazy[p]+=num; return ; } pushDown(p); int mid=(l+r)>>1; if(mid>=i) update_1(lson,i,j,num); if(mid<j) update_1(rson,i,j,num); pushUp(p);}void update_2(int l,int r,int p,LL i,LL j,LL num){ if(l>=i&&r<=j){ sum[p]=min(sum[p],num); mins[p]=min(mins[p],num); return ; } pushDown(p); int mid=(l+r)>>1; if(mid>=i) update_2(lson,i,j,num); if(mid<j) update_2(rson,i,j,num); pushUp(p);}void update_3(int l,int r,int p,LL i,LL j,LL num){ if(l>=i&&r<=j){ sum[p]=max(sum[p],num); mins[p]=max(mins[p],num); return ; } pushDown(p); int mid=(l+r)>>1; if(mid>=i) update_3(lson,i,j,num); if(mid<j) update_3(rson,i,j,num); pushUp(p);}int main(){ int n,q,T; //freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { mem(sum); mem(mins); scanf("%d%d",&n,&q); build(1,n,1); LL temp,a,b,c; while(q--) { scanf("%I64d",&temp); if(temp==1){ scanf("%I64d%I64d%I64d",&a,&b,&c); update_1(1,n,1,a,b,c); }else if(temp==2){ scanf("%I64d%I64d%I64d",&a,&b,&c); update_2(1,n,1,a,b,c); }else if(temp==3){ scanf("%I64d%I64d%I64d",&a,&b,&c); update_3(1,n,1,a,b,c); }else{ scanf("%I64d%I64d",&a,&b); ans_max=-0x3f3f3f3f3f3f; ans_min=0x3f3f3f3f3f3f; query(1,n,1,a,b); printf("%I64d %I64d\n",ans_min,ans_max); } } } return 0;}
0 0
- xtu oj 1238 线段树
- XTU 1238 线段树
- XTU 1238 Segment Tree (线段树)
- XTU OJ
- XTU OJ
- XTU OJ Highway(树的直径)
- XTU OJ 1160 Harry Potter
- xtu oj 1252Defense Tower
- xtu oj 1236 小数转分数
- XTU 1238 Binary String
- 约瑟夫问题 线段树Timus OJ 1521
- SWUN OJ 1749(DP + 线段树)
- 值域线段树 (玲珑OJ 1117)
- 线段树入门 南阳oj 119
- XTU OJ 1175 Hurry Up(三分法&&穷举法)
- XTU OJ 1163 查询成绩 (字符串+递归)
- XTU OJ 1210 Happy Number (暴力+打表)
- XTU OJ 1207 Welcome to XTCPC (字符串签到题)
- HBase运行必须要sudo
- 设计模式之一:单例模式
- Linux学习笔记
- HDU 1176- 免费馅饼
- tmux常用操作总结
- xtu oj 1238 线段树
- android调试神器Stetho
- dataTables-使用详细说明整理
- 向GitHub的一次提交
- svm算法 最通俗易懂讲解
- 欢迎使用CSDN-markdown编辑器
- CAN总线冲突裁决
- burpsuite_pro_v1.7.11使用介绍
- eclipse如何导入项目和文件