线段树——区间合并
来源:互联网 发布:大数据行业分析 编辑:程序博客网 时间:2024/06/01 09:09
题目:Hotel
题意:区间初始全0。两种操作:将区间某一段置0;查询超过指定长度的区间的最左端点(多个区间则取最左)
第一次做错,错在查询时,只是查询整个区间的最长连续子区间,可题目要求的只是超过一定长度的子区间,而不一定是最长的,所以应按左区间,跨左右区间,右区间的顺序递归查找满足要求的子区间。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define MAXN 50000#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int msum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2];int lable[MAXN<<2],idm[MAXN<<2];void pushUp(int l,int r,int rt) {//合并子区间 int m=(l+r)>>1; lsum[rt]=lsum[rt<<1]==m-l+1?m-l+1+lsum[rt<<1|1]:lsum[rt<<1]; rsum[rt]=rsum[rt<<1|1]==r-m?r-m+rsum[rt<<1]:rsum[rt<<1|1]; msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);// if(msum[rt]==msum[rt<<1]) idm[rt]=idm[rt<<1];// else if(msum[rt]==rsum[rt<<1]+lsum[rt<<1|1]) idm[rt]=m-rsum[rt<<1]+1;// else idm[rt]=idm[rt<<1|1];}void pushDown(int l,int r,int rt) {//标记下放 if(~lable[rt]) { int m=(l+r)>>1; lable[rt<<1]=lable[rt<<1|1]=lable[rt]; msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=lable[rt]*(m-l+1);//1清空 0占满 msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=lable[rt]*(r-m);// if(lable[rt]) idm[rt<<1]=l,idm[rt<<1|1]=m+1;// else idm[rt<<1]=idm[rt<<1|1]=-1; lable[rt]=-1; }}void build(int l,int r,int rt) { msum[rt]=lsum[rt]=rsum[rt]=r-l+1; lable[rt]=-1;// idm[rt]=l; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson);}void update(int x,int y,int w,int l,int r,int rt) { if(x<=l&&r<=y) { msum[rt]=lsum[rt]=rsum[rt]=w*(r-l+1); lable[rt]=w;// idm[rt]=w?l:-1; return ; } pushDown(l,r,rt); int m=(l+r)>>1; if(x<=m) update(x,y,w,lson); if(y>m) update(x,y,w,rson); pushUp(l,r,rt);}//int query(int w,int l,int r,int rt) {//错误的查询方式// int m=(l+r)>>1;// if(msum[rt<<1]>=w) return idm[rt<<1];// if(rsum[rt<<1]+lsum[rt<<1|1]>=w) return m-rsum[rt<<1]+1;// return idm[rt<<1|1];//}int query(int w,int l,int r,int rt) {if (l == r) return l;pushDown(l,r,rt);int m = (l + r) >> 1;if (msum[rt<<1] >= w) return query(w , lson);else if (rsum[rt<<1] + lsum[rt<<1|1] >= w) return m - rsum[rt<<1] + 1;return query(w , rson);}int main() {// ios::sync_with_stdio(false); int n,m,ins,a,b; scanf("%d%d",&n,&m); build(1,n,1); while(m--) { cin >> ins; if(ins==1) { scanf("%d",&a); if(msum[1]<a) {puts("0");continue;} int q=query(a,1,n,1); printf("%d\n",q); update(q,q+a-1,0,1,n,1); } else { scanf("%d%d",&a,&b); update(a,a+b-1,1,1,n,1); } } return 0;}
- 线段树—区间合并
- 线段树——区间合并
- LA3938——线段树区间合并
- poj3667_Hotel—线段树区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树-区间合并
- HDU 3397——Sequence operation(线段树,区间染色+区间异或+区间合并)
- 线段树——区间合并——hud1540
- POJ 3667——Hotel(线段树,区间合并)
- 线段树区间合并——POJ 3667
- 线段树区间合并——UVA 1400
- 谈区间合并线段树
- hdu3308 线段树区间合并
- poj3667线段树区间合并
- poj3667 线段树+区间合并
- opencv2.2 MFC picture控件中显示图片
- 《android课表》之metro风格
- 浙江大华2012笔试题+答案解析
- ubuntu 12 中文输入法的安装
- 阿里巴巴2011笔试题+答案解析
- 线段树——区间合并
- 百度2011招聘笔试题+答案解析
- oracle 备份与导入
- KMP算法
- cmd.ExecuteScalar()方法
- 腾讯2011年10月15日校招笔试+答案解析
- 腾讯2012实习生笔试题+答案解析
- 完整优化的SuffixTree代码
- Method Names and Non-ARC Compiled Code