poj 3667 线段树,区间合并
来源:互联网 发布:奥一网 网络问政 编辑:程序博客网 时间:2024/05/21 11:18
题意:给N 个空房间,有M次操作,1是 去连续x 房间为空的第一个房间号 && 房间号最小; 2:将[x ,x+y-1] 房间清空;
思路: 用mark ==0 表示当前这个区间状态未定,mark= 1 表示要将此区间的子区间全部清空(房间全部可使用) mark=2 表示 此区间的子区间 的房子全部入住满;
ms 为此区间最大连续为空的房间数; ls 为区间从最左端开始连续为空的房间数,rs 为区间从最右端开始连续为空的房间数;
len 为区间的总房间数; pos 记录ms 的起始房间号;
第二遍写时候犯很多逗比错误: build—tree() 时候没有管mark 的初始;
node(int ms=0,int rs=0,int ls=0) 懒省事只写了3 个变量,误以为这样就可以只给这三个变量赋值,其他不变! node() 函数是会把里面的东西全部重新替换的!没有写的变量系统随机生成数字!C++ 语法没认真学的后果;
#include<stdio.h>#include<string.h>#include<math.h>#include<string>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<list>#include<map>#include<set>using namespace std;const int N = 50010;int n, m;struct node{ int ms,ls,rs; int pos,len,mark; node(int ms=0,int ls=0,int rs=0,int len=0,int pos=0,int mark=0): ms(ms),ls(ls),rs(rs),len(len),pos(pos),mark(mark){}};node tree[N * 4];void tree_build(int st, int ed, int i){ int L = ed - st + 1; tree[i]=node(L, L, L, L, st, 0); if(st == ed) return ; int mid = (st + ed) >> 1; tree_build(st, mid, i * 2); tree_build(mid + 1, ed, i * 2 + 1);}void tree_down_data(int st, int ed, int i){ if(tree[i].mark == 0 || st == ed) return ; int mid = (st + ed) >> 1; int fi = i * 2, se = i * 2 + 1; if(tree[i].mark == 1){ int L = tree[fi].len; tree[fi] = node(L, L, L, L, st, 1); L = tree[se].len; tree[se] = node(L ,L, L, L, mid + 1, 1); } else if(tree[i].mark == 2){ int L = tree[fi].len; tree[fi] = node(0, 0, 0, L, st, 2); L = tree[se].len; tree[se] = node(0, 0, 0, L, mid + 1, 2); } tree[i].mark = 0;}int tree_query(int len, int st, int ed, int i){// printf("Q:len=%d, st = %d ,ed= %d ,i = %d\n",len,st,ed,i); tree_down_data(st, ed, i); if(tree[i].ms < len) return 0; if(st == ed){ return tree[i].pos; } int mid = (st + ed) >> 1; if(tree[i * 2].ms >= len) return tree_query(len, st, mid, i * 2); else if(tree[i * 2].rs + tree[i * 2 + 1].ls >= len) return mid - tree[i * 2].rs + 1; else return tree_query(len, mid + 1, ed , i * 2 + 1);}void tree_up_data(int st, int ed, int i){ int mid = (st + ed) >> 1; int fi = i * 2, se = i * 2 + 1; tree[i].ls = tree[fi].ls; if(tree[fi].ls == tree[fi].len) // 当左儿子全部为空时 tree[i].ls += tree[se].ls; // 加上右儿子的最大连续左区 tree[i].rs = tree[se].rs; if(tree[se].rs == tree[se].len) tree[i].rs += tree[fi].rs; tree[i].ms = max(tree[fi].rs + tree[se].ls , max(tree[fi].ms, tree[se].ms) ); // 当前区间的连续最大可以来自于左儿子最大,右儿子最大,或者是左儿子的右端+右儿子的左端; if(tree[i].ms == tree[fi].ms) tree[i].pos = tree[fi].pos; // pos 维护是连续为空的房间数最大 && 最靠近左端的起点; //要考虑如果tree[fi].ms ==tree[fi].rs + tree[se].ls || //tree[fi].ms == tree[se].ms 优先选取 tree[fi].pos; else if (tree[i].ms == tree[fi].rs + tree[se].ls) tree[i].pos = (st + ed) >> 1 - tree[fi].rs + 1; // 同理; else tree[i].pos = tree[se].pos;}void tree_add(int op, int x, int y, int st, int ed, int i){ tree_down_data(st, ed, i); if(x > ed || y < st) return ; if(x <= st && y >= ed) { if(op == 1){ //房间全部标记为可以入住; int L = tree[i].len ; tree[i] = node(L ,L, L, L, st, op); } else{ int L = tree[i].len; tree[i] = node(0, 0, 0, L, st, op); } return ; } int mid = (st + ed) >> 1; tree_add(op, x, y, st, mid, i * 2); tree_add(op, x, y, mid + 1, ed, i * 2 + 1); tree_up_data(st, ed, i);}void debug(int st, int ed, int i){ printf("st=%d ed= %d i= %d:\n",st, ed, i); printf("ms=%d,ls=%d,rs=%d,len=%d,mark=%d\n",tree[i].ms,tree[i].ls,tree[i].rs,tree[i].len,tree[i].mark); if(st == ed) return ; int mid = (st + ed) >> 1; debug(st, mid ,i * 2); debug(mid + 1, ed, i * 2 + 1);}int main(){//freopen("in.in","r",stdin); while(~scanf("%d%d",&n,&m)){ tree_build(1, n, 1);// debug(1, n, 1); int op, x, y; while(m--){ scanf("%d",&op); if(op == 1){ scanf("%d", &x); int ans = tree_query(x, 1, n, 1); cout << ans << endl; if(ans == 0) continue; // 注意ans = 0 跳过! tree_add(2, ans, ans + x -1, 1, n, 1);// debug(1, n, 1); } else { scanf("%d%d",&x,&y); tree_add(1, x, x + y - 1 , 1, n, 1); } } }return 0;}
一星期前的写法:
#include<stdio.h>#include<string.h>#include<math.h>#include<string>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<list>#include<map>#include<set>using namespace std;const int maxn=50100;struct node{ int ls,rs,ms,pos,mark; node(int ls=0,int rs=0,int ms=0,int pos=0,int mark=0):ls(ls),rs(rs),ms(ms),pos(pos),mark(mark){}}tree[4*maxn];void build_tree(int st,int ed,int i){ tree[i]=node(ed-st+1,ed-st+1,ed-st+1,st,0); if(st==ed) return ; int mid=(st+ed)>>1; build_tree(st,mid,i*2); build_tree(mid+1,ed,i*2+1);}bool is_all_clear(int st,int ed,int i){ if(tree[i].ls==ed-st+1) return 1; else return 0;}void update(int st,int ed,int i){ if(tree[i].mark==0) return; int mid=(st+ed)/2; if(tree[i].mark==1){ tree[i*2]=node(mid-st+1,mid-st+1,mid-st+1,st,1); tree[i*2+1]=node(ed-mid,ed-mid,ed-mid,mid+1,1); } else { tree[i*2]=node(0,0,0,st,2); tree[i*2+1]=node(0,0,0,mid+1,2); } tree[i].mark=0;}int query(int len,int st,int ed,int i){ update(st,ed,i); if(tree[i].ms<len) return 0; if(tree[i].ms==len) return tree[i].pos; int mid=(st+ed)/2; if(tree[i*2].ms>=len) return query(len,st,mid,i*2); if(tree[i*2].rs+tree[i*2+1].ls>=len) return mid-tree[i*2].rs+1; return query(len,mid+1,ed,i*2+1);}void get_max(node &pre,node &p1,node &p2,int mid){ int len=p1.rs+p2.ls; if(p1.ms>=len && p1.ms>=p2.ms){ pre.ms=p1.ms; pre.pos=p1.pos; return; } else if(len>p1.ms && len>=p2.ms){ pre.ms=len; pre.pos=mid-p1.rs+1; return ; } else if(p2.ms>p1.ms && p2.ms>len){ pre.ms=p2.ms; pre.pos=p2.pos; return ; }}void change(int x,int y,int st,int ed,int i,bool fg){ if(x>ed || y<st) return ; if(x<=st && y>=ed) { if(fg) tree[i]=node(0,0,0,st,2); else tree[i]=node(ed-st+1,ed-st+1,ed-st+1,st,1); return; } update(st,ed,i); int mid=(st+ed)/2; change(x,y,st,mid,i*2,fg); change(x,y,mid+1,ed,i*2+1,fg); tree[i].ls=tree[i*2].ls; if(is_all_clear(st,mid,i*2)) tree[i].ls+=tree[i*2+1].ls; tree[i].rs=tree[i*2+1].rs; if(is_all_clear(mid+1,ed,i*2+1)) tree[i].rs+=tree[i*2].rs; get_max(tree[i],tree[i*2],tree[i*2+1],mid);}int main(){// freopen("in.in","r",stdin); int n,m,choice,st,len; while(~scanf("%d%d",&n,&m)){ build_tree(1,n,1); while(m--){ scanf("%d",&choice); if(choice==1){ scanf("%d",&len); int ans=query(len,1,n,1); cout<<ans<<endl; if(ans) change(ans,ans+len-1,1,n,1,1); } else{ scanf("%d%d",&st,&len); change(st,st+len-1,1,n,1,0); } } } return 0;}
0 0
- poj 3667 区间合并 区间线段树
- poj 3667【线段树-区间合并】
- POJ 3667 Hotel 线段树区间合并
- poj 3667 Hotel 线段树区间合并
- poj 3667 线段树 区间合并
- POJ 3667 Hotel 线段树 区间合并
- poj 3667 线段树合并区间
- Poj 3667 Hotel 线段树 区间合并
- POJ 3667-hotel(线段树区间合并)
- poj 3667 线段树,区间合并
- POJ 3667 Hotel. (线段树 区间合并)
- 【线段树】POJ 3667 Hotel 区间合并
- POJ-3667 线段树(区间合并)
- POJ 3667 Hotel ( 线段树区间合并 )
- POJ 3667 线段树区间合并
- 线段树 区间合并 poj 3667 Hotel
- poj 3667 线段树区间合并
- POJ 3667 Hotel 线段树 区间合并
- 浅析企业微信营销那点事儿
- 数据结构笔记(1)算法数据结构的基本概念O估计法
- 笔记53--Service学习之概念篇,杠杠的难懂
- Codeforces Round #254 (Div. 2)(并查集,线段树)
- 追随心的选择,勇敢前行
- poj 3667 线段树,区间合并
- SQL_标量值函数
- Android 中声音的处理一:MediaPlayer
- shell分析nginx access log日志
- Microsoft Visual SourceSafe
- 搭载传智播客IT列车,筑梦起航
- jQuery 操作 input 之 checkbox
- USACO-cha1-sec1.5 Prime Palindromes
- Android检测网络状态,判断当前网络是否可用