HDU 4902 Nice boat --线段树(区间更新)
来源:互联网 发布:mac apache forbidden 编辑:程序博客网 时间:2024/04/29 03:51
题意:给一个数字序列,第一类操作是将[l,r]内的数全赋为x ,第二类操作是将[l,r]中大于x的数赋为该数与x的gcd,若干操作后输出整个序列。
解法: 本题线段树要维护的最重要的东西就是一个区间内所有数是否相等的标记。只维护这个东西都可以做出来。 我当时想歪了,想到维护Max[rt]表示该段的最大值,最大值如果<=x的话就不用更新了,但是好像加了这个“优化”跑的更慢了。
我想大概是因为如果两个子树最大值或者整个两个子树的数不完全相等的话,根本不能直接下传这个值或者下传gcd,因为你不知道要更新哪个值。所以要维护一个区间是否相等的标记,而且这样最坏情况下也是更新到叶子节点,正好使我们要更新的。
只要弄懂了要维护什么,其余的就不难了。
代码1:(加一个Max标记)
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;#define N 100007int Max[4*N],mark[4*N]; //mark[rt]=-1表示此段值不统一,否则mark[rt]会等于该段的统一值int gcd(int a,int b){ if(!b) return a; return gcd(b,a%b);}void pushup(int rt){ Max[rt] = max(Max[2*rt],Max[2*rt+1]);}void pushdown(int l,int r,int rt){ if(mark[rt] != -1) //此段值相同 { mark[2*rt] = mark[2*rt+1] = mark[rt]; Max[2*rt] = Max[2*rt+1] = Max[rt]; mark[rt] = -1; }}void build(int l,int r,int rt){ mark[rt] = -1; if(l == r) { scanf("%d",&Max[rt]); mark[rt] = Max[rt]; return; } int mid = (l+r)/2; build(l,mid,2*rt); build(mid+1,r,2*rt+1); pushup(rt);}void update(int l,int r,int aa,int bb,int val,int tag,int rt){ if(aa <= l && bb >= r) { if(tag == 1) { Max[rt] = mark[rt] = val; return; } else { if(mark[rt] != -1) //此段值相等 { if(Max[rt] > val) //要更新 Max[rt] = mark[rt] = gcd(mark[rt],val); return; } } } pushdown(l,r,rt); int mid = (l+r)/2; if(aa <= mid) update(l,mid,aa,bb,val,tag,2*rt); if(bb > mid) update(mid+1,r,aa,bb,val,tag,2*rt+1); pushup(rt);}void print(int l,int r,int rt){ if(l == r) { printf("%d ",Max[rt]); return; } pushdown(l,r,rt); int mid = (l+r)/2; print(l,mid,2*rt); print(mid+1,r,2*rt+1);}int main(){ int n,m,i,t,tag,aa,bb,val; scanf("%d",&t); while(t--) { scanf("%d",&n); build(1,n,1); scanf("%d",&m); while(m--) { scanf("%d%d%d%d",&tag,&aa,&bb,&val); update(1,n,aa,bb,val,tag,1); } print(1,n,1); puts(""); } return 0;}
代码2:(只维护一个)
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;#define N 100007int Max[4*N];int gcd(int a,int b){ if(!b) return a; return gcd(b,a%b);}void pushup(int rt){ if(Max[2*rt] == Max[2*rt+1]) Max[rt] = Max[2*rt];}void pushdown(int l,int r,int rt){ if(Max[rt] != -1) Max[2*rt] = Max[2*rt+1] = Max[rt], Max[rt] = -1;}void build(int l,int r,int rt){ Max[rt] = -1; if(l == r) { scanf("%d",&Max[rt]); return; } int mid = (l+r)/2; build(l,mid,2*rt); build(mid+1,r,2*rt+1); pushup(rt);}void update(int l,int r,int aa,int bb,int val,int tag,int rt){ if(aa <= l && bb >= r) { if(tag == 1) { Max[rt] = val; return; } else { if(Max[rt] != -1) { if(Max[rt] > val) //下面有比它大的,即有要更新的 Max[rt] = gcd(Max[rt],val); return; } } } pushdown(l,r,rt); int mid = (l+r)/2; if(aa <= mid) update(l,mid,aa,bb,val,tag,2*rt); if(bb > mid) update(mid+1,r,aa,bb,val,tag,2*rt+1); pushup(rt);}void print(int l,int r,int rt){ if(l == r) { printf("%d ",Max[rt]); return; } pushdown(l,r,rt); int mid = (l+r)/2; print(l,mid,2*rt); print(mid+1,r,2*rt+1);}int main(){ int n,m,i,t,tag,aa,bb,val; scanf("%d",&t); while(t--) { scanf("%d",&n); build(1,n,1); scanf("%d",&m); while(m--) { scanf("%d%d%d%d",&tag,&aa,&bb,&val); update(1,n,aa,bb,val,tag,1); } print(1,n,1); puts(""); } return 0;}
0 0
- HDU 4902 Nice boat(线段树 区间更新)
- 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·单点更新)
- 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(线段树)
- HDU 4902 Nice boat(线段树)
- hdu 4902 Nice boat 线段树
- hdu 4902 Nice boat (线段树)
- HDU 4902 Nice boat(线段树)
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
- HDU 5083 Instruction --模拟
- HDU 5084 HeHe --找规律
- Codeforces Round #275 Div.1 B Interesting Array --线段树
- HDU 4782 Beautiful Soup --模拟
- HDU 4777 Rabbit Kingdom --容斥原理+树状数组
- HDU 4902 Nice boat --线段树(区间更新)
- HDU 4941 Magical Forest --STL Map应用
- POJ 1990 MooFest --树状数组
- POJ 2464 Brownie Points II --树状数组
- POJ 3416 Crossing --离线+树状数组
- HDU 4286 Data Handler --双端队列
- HDU 4282 A very hard mathematic problem --枚举+二分(或不加)
- 一些整数类型的表示范围
- android.os.BadParcelableException: ClassNotFoundException when unmarshalling