[kuangbin带你飞]专题七 线段树 I HDU 1540
2016-09-22 19:27
411 查看
题目地址:https://vjudge.net/contest/66989#problem/I
思路:建树是用ls,rs,ms,分别代表该区间内从左端点开始的最长连续区间,从右端点开始的,以及整个区间内的。对于每个区间,初始化时显然为r-l+1。在更新时,以T[k]为例,显然他的ls最小为T[2*k]区间的ls,如果他的ls等于整个区间的长度,说明他与T[2*k+1]相连,则加上T[2*k+1]的ls。同理,rs的更新也是一样的判断。而ms,首先他至少为2*k,2*k+1的ms中的最大者。然后将这个值与将2*k,2*k+1的rs,ls相加再比较,这就得到了k的新ms。
而查询时,相对简单一些,但是在递归查找时也一样,要考虑是否相连,当与另一侧相连时,同样需要加上对应的ls或者rs。线段树好难啊……这种操作比较复杂的题目还是只能敲个build就滚粗了……思路参考了kuangbin大神的题解,随便百度一下就有了。还有个这题要用EOF,我真没看到题目哪里说了啊……
AC代码:
思路:建树是用ls,rs,ms,分别代表该区间内从左端点开始的最长连续区间,从右端点开始的,以及整个区间内的。对于每个区间,初始化时显然为r-l+1。在更新时,以T[k]为例,显然他的ls最小为T[2*k]区间的ls,如果他的ls等于整个区间的长度,说明他与T[2*k+1]相连,则加上T[2*k+1]的ls。同理,rs的更新也是一样的判断。而ms,首先他至少为2*k,2*k+1的ms中的最大者。然后将这个值与将2*k,2*k+1的rs,ls相加再比较,这就得到了k的新ms。
而查询时,相对简单一些,但是在递归查找时也一样,要考虑是否相连,当与另一侧相连时,同样需要加上对应的ls或者rs。线段树好难啊……这种操作比较复杂的题目还是只能敲个build就滚粗了……思路参考了kuangbin大神的题解,随便百度一下就有了。还有个这题要用EOF,我真没看到题目哪里说了啊……
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn=5e4+10; struct seq{ int l,r,ls,rs,ms;//左侧开始的最大连续区间,右侧开始的最大连续空间,区间内最长连续空间 }T[maxn*4]; void build(int l,int r,int k) { T[k].l=l,T[k].r=r; T[k].ls=T[k].rs=T[k].ms=r-l+1; if(l==r) return; int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); } void update(int n,int k,int v) { if(T[k].l==n && T[k].r==n) { if(v)//摧毁 T[k].ls=T[k].rs=T[k].ms=0; else T[k].ls=T[k].rs=T[k].ms=1; return; } else { int mid=(T[k].l+T[k].r)>>1; if(n<=mid) update(n,k<<1,v); else if(n>mid) update(n,k<<1|1,v); T[k].ls=T[k<<1].ls; T[k].rs=T[k<<1|1].rs; T[k].ms=max(T[k<<1].ms,T[k<<1|1].ms); T[k].ms=max(T[k].ms,T[k<<1].ls+T[k<<1|1].rs); if(T[k<<1].ls==T[k<<1].r-T[k<<1].l+1) T[k].ls+=T[k<<1|1].ls;//判断左右连续区间是否相连 if(T[k<<1|1].rs==T[k<<1|1].r-T[k<<1|1].l+1) T[k].rs+=T[k<<1].rs; } } int search(int n,int k) { if(T[k].l==T[k].r || T[k].ms==0 || T[k].ms==T[k].r-T[k].l+1) { return T[k].ms; } int mid=(T[k].r+T[k].l)>>1; if(n<=mid) { if(n>=T[k<<1].r-T[k<<1].rs+1)//相连 return search(n,k<<1)+search(mid+1,k<<1|1); else return search(n,k<<1); } else { if(n<=T[k<<1|1].l+T[k<<1|1].ls-1) return search(n,k<<1|1)+search(mid,k<<1); else return search(n,k<<1|1); } } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { stack<int>k; memset(T,0,sizeof(T)); build(1,n,1); while(m--) { char a[2]; scanf("%s",a); if(a[0]=='D') { int a; scanf("%d",&a); k.push(a); update(a,1,1); } else if(a[0]=='Q') { int a; scanf("%d",&a); printf("%d\n",search(a,1)); } else if(a[0]=='R') { int a; a=k.top(); k.pop(); update(a,1,0); } } } }
相关文章推荐
- [kuangbin带你飞]专题七 线段树 A HDU 1166
- 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵
- [kuangbin带你飞]专题七 线段树 题解(未完)
- [kuangbin带你飞]专题七 线段树 C - A Simple Problem with Integers
- [kuangbin带你飞]专题七 线段树 E - Just a Hook
- [kuangbin带你飞]专题七 线段树
- 【算法系列学习】线段树 单点覆盖,区间查询最大值 [kuangbin带你飞]专题七 线段树 B - I Hate It
- [kuangbin带你飞]专题七 线段树 B - I Hate It(单点修改,区间最大值)
- [kuangbin带你飞]专题七 线段树 A - 敌兵布阵 (单点修改,区间求和)
- [kuangbin带你飞]专题七 线段树 J HDU 3974
- 【算法系列学习】线段树 区间修改,区间求和 [kuangbin带你飞]专题七 线段树 C - A Simple Problem with Integers
- [kuangbin带你飞]专题七 线段树 B HDU 1754
- [kuangbin带你飞]专题七 线段树 C POJ 3468
- [kuangbin带你飞]专题七 线段树 G POJ 3264
- [kuangbin带你飞]专题七 线段树 F - Count the Colors(颜色覆盖)
- [kuangbin带你飞]专题十二 基础DP1 I HDU 1257
- [kuangbin带你飞]专题七 线段树 G POJ 3264
- [kuangbin带你飞]专题七 线段树 H HDU-4027
- [kuangbin带你飞]专题七 线段树 【A、B、C、E、G、H】
- [kuangbin带你飞]专题七 线段树 H HDU4027