【线段树区间合并】BZOJ1593-[Usaco2008 Feb]Hotel 旅馆

好无聊,以前写过没什么好讲的,水过。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #define lson l,mid,rt<<1
  5 #define rson mid+1,r,rt<<1|1
  6 #define root 1
  7 using namespace std;
  8 const int MAXN=50000+50;
  9 int n,m;
 10 int lsum[MAXN<<2],rsum[MAXN<<2],msum[MAXN<<2];
 11 int cover[MAXN<<2];//区间覆盖
 12
 13 void pushdown(int l,int r,int rt)
 14 {
 15     int mid=(l+r)>>1;
 16     if (cover[rt]!=-1)
 17     {
 18         cover[rt<<1]=cover[rt<<1|1]=cover[rt];
 19         if (cover[rt]==1)
 20             lsum[rt<<1]=lsum[rt<<1|1]=rsum[rt<<1]=rsum[rt<<1|1]=msum[rt<<1]=msum[rt<<1|1]=0;
 21         else
 22         {
 23             lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=mid-l+1;
 24             lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=r-mid;
 25         }
 26         cover[rt]=-1;
 27     }
 28 }
 29
 30 void pushup(int l,int r,int rt)
 31 {
 32     int mid=(l+r)>>1;
 33     lsum[rt]=lsum[rt<<1];
 34     if (lsum[rt<<1]==(mid-l+1)) lsum[rt]+=lsum[rt<<1|1];
 35     rsum[rt]=rsum[rt<<1|1];
 36     if (rsum[rt<<1|1]==(r-mid)) rsum[rt]+=rsum[rt<<1];
 37     msum[rt]=max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1]));
 38 }
 39
 40 void update(int L,int R,int c,int l,int r,int rt)
 41 {
 42     if (L<=l && r<=R)
 43     {
 44         msum[rt]=lsum[rt]=rsum[rt]=c? 0:(r-l+1);
 45         cover[rt]=c;
 46         return;
 47     }
 48     pushdown(l,r,rt);
 49     int mid=(l+r)>>1;
 50     if (L<=mid) update(L,R,c,lson);
 51     if (mid<R) update(L,R,c,rson);
 52     pushup(l,r,rt);
 53 }
 54
 55 int query(int q,int l,int r,int rt)
 56 {
 57     if (l==r) return l;
 58     pushdown(l,r,rt);
 59     int mid=(l+r)>>1;
 60     if (msum[rt<<1]>=q) return(query(q,lson));
 61     if (rsum[rt<<1]+lsum[rt<<1|1]>=q) return(mid-rsum[rt<<1]+1);
 62     return (query(q,rson));
 63 }
 64
 65 void build(int l,int r,int rt)
 66 {
 67     lsum[rt]=rsum[rt]=msum[rt]=r-l+1;
 68     cover[rt]=-1;
 69     if (l==r) return;
 70     int mid=(l+r)>>1;
 71     build(lson);
 72     build(rson);
 73 }
 74
 75 void solve()
 76 {
 77     build(1,n,1);
 78     for (int i=0;i<m;i++)
 79     {
 80         int op,d,x;
 81         scanf("%d",&op);
 82         if (op==1)
 83         {
 84             scanf("%d",&d);
 85             if (msum[root]<d) puts("0");
 86             else
 87             {
 88                 x=query(d,1,n,1);
 89                 printf("%d\n",x);
 90                 update(x,x+d-1,1,1,n,1);
 91             }
 92         }
 93         else
 94         {
 95             scanf("%d%d",&x,&d);
 96             update(x,x+d-1,0,1,n,1);
 97         }
 98     }
 99 }
100
101 int main()
102 {
103     scanf("%d%d",&n,&m);
104     solve();
105     return 0;
106 }
时间: 2024-10-01 06:00:04

【线段树区间合并】BZOJ1593-[Usaco2008 Feb]Hotel 旅馆的相关文章

bzoj1593 [Usaco2008 Feb]Hotel 旅馆

1593: [Usaco2008 Feb]Hotel 旅馆 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 807  Solved: 447[Submit][Status][Discuss] Description 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排

【分块】bzoj1593 [Usaco2008 Feb]Hotel 旅馆

分块,记录每个块内包括左端点的最大连续白段的长度, 整个块内的最大连续白段的长度, 和包括右端点的最大连续白段的长度. Because 是区间染色,所以要打标记. 至于怎样在O(sqrt(n))的时间内找到最左的白色段呢?非常恶心…… 要考虑跨块的白段和块内的白段,并且顺序不能反.(代码中高亮的部分) 这题完全体现不出分块编程复杂度低的优势,完全逊色于线段树. So 综上,对于要进行复杂的成段修改的题目,分块的编程复杂度较高,几乎没有优势,不推荐写. 1 #include<cstdio> 2

1593: [Usaco2008 Feb]Hotel 旅馆 (线段树)

1593: [Usaco2008 Feb]Hotel 旅馆 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 451  Solved: 262[Submit][Status][Discuss] Description 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排

POJ 3667 Hotel(线段树区间合并)

Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Stree

POJ 3667 Hotel 【线段树 区间合并 + Lazy-tag】

Hotel Time Limit: 3000MS Memory Limit: 65536K 链接:POJ 3667   Description The cows are journeying north to ThunderBay in Canada to gain cultural enrichment and enjoy a vacation on the sunnyshores of Lake Superior. Bessie, ever the competent travel agen

Poj 3667——hotel——————【线段树区间合并】

Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13124   Accepted: 5664 Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie

线段树(区间合并) POJ 3667 Hotel

题目传送门 1 /* 2 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 3 输入 2 a b:将[a,a+b-1]的房间清空 4 线段树(区间合并):lsum[]统计从左端点起最长连续空房间数,rsum[]类似,sum[]统计区间最长连续的空房间数, 5 它有三种情况:1.纯粹是左端点起的房间数:2.纯粹是右端点的房间数:3.当从左(右)房间起都连续时,加上另一个子节点 6 从左(右)房间起的数,sum[]再求最大值更新维护.理解没错,表达能力不足 7 详细解释:htt

POJ 3667 Hotel (线段树区间合并 )

Language: Default Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12417   Accepted: 5346 Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lak

POJ 3667 Hotel (初遇线段树区间合并)

题意: 有一个线段,从1到n,下面m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作 1 w 表示在总区间内查询一个长度为w的可用区间并且要最靠左,能找到的话返回这个区间的左端点并占用了这个区间,找不到返回0 2 a len , 表示从单位a开始,清除一段长度为len的区间(将其变为可用,不被占用),不需要输出. 思路: 这是第一次遇到线段树区间合并的题目,写下感悟,还是对线段的更新和查询工作,但是查询的对象的性质已经不像单点那样,查询的是某个线段的最大可用区间是多少,还要一并