-
I - Colonial Mansions
- Gym - 101962I
- 题意:两种操作1.单点更新.2以一个点为中心查询他能到达的点的个数,移动规则为:
- 每一个点都有一个高度,只能往相邻的点移动 而且|hu-hv|<=H.
- 思路:建立线段树最底层存的是 区间内每一个点与它前一个点的差,第一个点没有前面差设置为0,查询到它的时候特判。
- 线段树区间维护的是这段区间中最大的那个差,然后点更新只需更新外部数组中的数字然后进行updata 那个位置,
- 与它后一个位置,这里也需要进行特判当后一个超过N时无需更新,最核心的就是query了
- 我是进行分段查询 给的位置为o那么我查询o-n与1-n两个区间,两种不同的查询方式,
- 因为有效的答案不仅仅要满足区间内最大的相邻的差值不超过H还必须满足从位置o能够一直到达这个区间才行
- 所以o-n查询时先递归左区间看看是否能够连续不断,如果连续不断这样才有意义进行查询右子区间
- 同样的,进行查询1-o时先判段递归右子区间是否连续,如果连续不断这样才有意义进行查询左子区间。
- 有许多细节需要处理,比如mid与(l,r)的大小问题,还有递归到最底层tree[root].l==tree[root].r,都需要进行相应的处理
- emmmmm调了two hours. 需要细细体会-by-SDUT-QYN。
-
#include<bits/stdc++.h> using namespace std; #define maxn 500000+100 int n,q,a[maxn],ord,type,H,sum; struct node { int l,r,di; } tree[maxn*4]; void build(int root,int l,int r) { tree[root].l=l; tree[root].r=r; if(l==r) { if(l==1) tree[root].di=0; else tree[root].di=abs(a[l]-a[l-1]); return ; } int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); tree[root].di=max(tree[root*2].di,tree[root*2+1].di); } void updata(int root,int o) { if(tree[root].l==o&&tree[root].r==o) { tree[root].di=abs(a[o]-a[o-1]); return ; } int mid=(tree[root].l+tree[root].r)/2; if(o<=mid)updata(root*2,o); else updata(root*2+1,o); tree[root].di=max(tree[root*2].di,tree[root*2+1].di); } bool queryr(int root,int l,int r) { if(tree[root].r<l) return false; if(tree[root].l==l&&tree[root].r==r&&tree[root].di<=H) { if(l==1) sum-=1; sum+=r-l+1; return 1; } if(tree[root].l==tree[root].r) return false; int mid=(tree[root].l+tree[root].r)/2; if(mid>=l) { if(queryr(2*root,l,mid)) queryr(2*root+1,mid+1,r); } else queryr(2*root+1,l,r); } bool queryl(int root,int l,int r) { if(tree[root].l>r) return false; if(tree[root].l==l&&tree[root].r==r&&tree[root].di<=H) { if(l==1) sum-=1; sum+=r-l+1; return 1; } if(tree[root].l==tree[root].r) return false; int mid=(tree[root].l+tree[root].r)/2; if(mid<r) { if(queryl(2*root+1,mid+1,r)) queryl(2*root,l,mid); } else queryl(2*root,l,r); } int main() { scanf("%d%d",&n,&q); for(int i=1; i<=n; i++) scanf("%d",&a[i]); build(1,1,n); while(q--) { scanf("%d%d%d",&type,&ord,&H); if(type==1) { a[ord]=H; updata(1,ord); if(ord+1<=n) updata(1,ord+1); } else { sum=0; queryl(1,1,ord); queryr(1,ord+1,n); printf("%d\n",sum+1); } } return 0; }
I - Colonial Mansions Gym -线段树-Change
最新推荐文章于 2020-07-03 21:20:04 发布