HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
2014-08-11 16:30
204 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902
解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作。
线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作,
进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明这个区间的值都是相同的,但现在我只要在这个区间的一部分进行1操作,所以
我要先把这个节点的最大的最小值往下压,直到找到了要操作的区间。
进行2操作时,如果该区间的最大值都小于x,则可以直接退出,如果最大值大于x,则表示这个区间可以进行gcd操作,然后继续往下,直到找到最大值跟最小值相等的区间才开始
进行gcd操作,进行gcd操作之后不要忘了更新父节点的最大最小值。
View Code
解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作。
线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作,
进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明这个区间的值都是相同的,但现在我只要在这个区间的一部分进行1操作,所以
我要先把这个节点的最大的最小值往下压,直到找到了要操作的区间。
进行2操作时,如果该区间的最大值都小于x,则可以直接退出,如果最大值大于x,则表示这个区间可以进行gcd操作,然后继续往下,直到找到最大值跟最小值相等的区间才开始
进行gcd操作,进行gcd操作之后不要忘了更新父节点的最大最小值。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 100005 struct node { int Max,Min,l,r; }tree[4*maxn]; void build(int p) { if(tree[p].l == tree[p].r) return ; int mid = (tree[p].l + tree[p].r) / 2; tree[2*p].Max = tree[2*p+1].Max = -1; tree[2*p].Min = tree[2*p+1].Min = 0x7fffffff; tree[2*p].l = tree[p].l; tree[2*p].r = mid; tree[2*p+1].l = mid + 1; tree[2*p+1].r = tree[p].r; build(2*p); build(2*p+1); } void push(int p,int l,int d) { tree[p].Max = max(tree[p].Max,d); tree[p].Min = min(tree[p].Min,d); if(tree[p].l == tree[p].r) return ; int mid = (tree[p].l + tree[p].r) / 2; if(l <= mid) push(2*p,l,d); else push(2*p+1,l,d); } int gcd(int a,int b) { return b == 0? a : gcd(b,a%b); } void oper1(int p,int l,int r,int x) { if(tree[p].l == l && tree[p].r == r) { tree[p].Max = tree[p].Min = x; return ; } int mid = (tree[p].l + tree[p].r) / 2; if(tree[p].Max == tree[p].Min) { oper1(2*p+1,mid+1,tree[p].r,tree[p].Max); //先把当前区间的值往下压 oper1(2*p,tree[p].l,mid,tree[p].Max); } tree[p].Max = max(tree[p].Max,x); tree[p].Min = min(tree[p].Min,x); if(r <= mid) oper1(2*p,l,r,x); else if(l <= mid && r > mid) { oper1(2*p,l,mid,x); oper1(2*p+1,mid+1,r,x); } else oper1(2*p+1,l,r,x); } void oper2(int p,int l,int r,int x) { int mid = (tree[p].l + tree[p].r) / 2; if(tree[p].l == l && tree[p].r == r) { if(tree[p].Max < x) return ; //最大的都不可以进行gcd操作,直接退出 if(tree[p].Max == tree[p].Min) //找到了值都相同的区间,可以直接进行gcd操作 { if(tree[p].Max > x) tree[p].Max = tree[p].Min = gcd(tree[p].Max,x); return ; } else if(tree[p].Max > x) { oper2(2*p,l,mid,x); oper2(2*p+1,mid+1,r,x); } return ; } if(tree[p].Max == tree[p].Min) //还没找到操作的区间之前碰到了这个,则也要通过1操作,把这个节点的值往下压 { oper1(2*p,tree[p].l,mid,tree[p].Max); oper1(2*p+1,mid+1,tree[p].r,tree[p].Max); } if(r <= mid) oper2(2*p,l,r,x); else if(l <= mid && r > mid) { oper2(2*p,l,mid,x); oper2(2*p+1,mid+1,r,x); } else oper2(2*p+1,l,r,x); if(tree[p].l != tree[p].r) //记得更新父节点的最大最小值 { tree[p].Max = max(tree[2*p].Max,tree[2*p+1].Max); tree[p].Min = min(tree[2*p].Min,tree[2*p+1].Min); } } int query(int p,int l) { int mid = (tree[p].l + tree[p].r) / 2; if(tree[p].Max == tree[p].Min) return tree[p].Max; if(l <= mid) return query(2*p,l); else return query(2*p+1,l); } int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); tree[1].Max = -1; tree[1].Min = 0x7fffffff; tree[1].l = 1; tree[1].r = n; build(1); int d; for(int i = 1;i <= n;++i) { scanf("%d",&d); push(1,i,d); } int q,t,l,r,x; scanf("%d",&q); while(q--) { scanf("%d%d%d%d",&t,&l,&r,&x); if(t == 1) oper1(1,l,r,x); else oper2(1,l,r,x); } for(int i = 1;i <= n;++i) //输出有点不同,PE了好几次,最后也是有空格的 printf("%d ",query(1,i)); puts(""); } return 0; }
View Code
相关文章推荐
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
- 2014多校第四场1006 HDU 4902 Nice boat 线段树 区间更新问题
- hdu 4902 Nice boat 多校第四场 线段树的区间置数+区间更新
- 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)
- HDU 4902 Nice boat(线段树 区间更新)
- HDU 4902 Nice boat --线段树(区间更新)
- HDU 4902 Nice boat --线段树(区间更新)
- 线段树 + 区间更新 ----- HDU 4902 : Nice boat
- hdu 4902 Nice boat(线段树区间更新lazytag·单点更新)
- HDU 4902 Nice boat 线段树(区间更新)
- HDU 4902 Nice boat(线段树 区间更新)
- HDU 4902 Nice boat 线段树 区间更新
- hdu 4902 Nice boat 2014年多校联合第四场
- HDU 4902 2014多校联赛第四场1006 Nice boat
- hdu 4902 Nice boat(线段树区间修改,输出最终序列)
- 线段树 hdu 1166 敌兵布阵 单点更新区间求和
- hdu 3874 Necklace 线段树单点更新区间求和
- HDU 3308 LCIS 线段树区间更新
- hdu1166敌兵布阵(线段树---单点更新,区间求值)
- HDU-1698(线段树_区间更新_java手写)