poj3667 hotel(线段树区间合并)

http://poj.org/problem?id=3667

之前网络赛水过一道区间合并的题 当时是全靠运气试对的 。

昨天纠结了一晚上也没看出来哪错,改的都跟人家代码一样了还是不对,今天又重新敲了一遍,莫名的就对了,,

开两个数组分别存这个区间两端点的连续区间 再开一标记数组 用来更新 向上向下都要更新

View Code
 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 using namespace std;

 6 #define N 50010

 7 int s[N<<2],kc[N<<2],lc[N<<2],rc[N<<2];

 8 void build(int l,int r,int w)

 9 {

10     s[w] = lc[w] = rc[w] = r-l+1;

11     kc[w] = -1;

12     if(l==r)

13     return ;

14     int m = (l+r)/2;

15     build(l,m,w<<1);

16     build(m+1,r,w<<1|1);

17 }

18 void pushdown(int w,int c)

19 {

20     if(kc[w]!=-1)

21     {

22         kc[w<<1] = kc[w<<1|1] = kc[w];

23         s[w<<1] = lc[w<<1] = rc[w<<1] = kc[w]?0:c-(c>>1);

24         s[w<<1|1] = lc[w<<1|1] = rc[w<<1|1] = kc[w]?0:c>>1;

25         kc[w] = -1;

26     }

27 }

28 void pushup(int w,int c)

29 {

30     lc[w] = lc[w<<1];

31     rc[w] = rc[w<<1|1];

32     if(lc[w]==c-(c>>1))

33     lc[w]+=lc[w<<1|1];

34     if(rc[w]==c>>1)

35     rc[w]+=rc[w<<1];

36     s[w] = max(rc[w<<1]+lc[w<<1|1],max(s[w<<1],s[w<<1|1]));//找出区间中最长的连续段

37 }

38 void update(int a,int b,int c,int l,int r,int w)

39 {

40     if(l>=a&&b>=r)

41     {

42         s[w] = lc[w] = rc[w] = c?0:r-l+1;

43         kc[w] = c;

44         return ;

45     }

46     pushdown(w,r-l+1);

47     int m = (l+r)>>1;

48     if(a<=m)

49     update(a,b,c,l,m,w<<1);

50     if(b>m)

51     update(a,b,c,m+1,r,w<<1|1);

52     pushup(w,r-l+1);

53 }

54 int query(int c,int l,int r,int w)

55 {

56     if(l==r)

57     return l;

58     pushdown(w,r-l+1);

59     int m = (l+r)>>1;

60     if(s[w<<1]>=c)

61     return query(c,l,m,w<<1);

62     else

63     if(rc[w<<1]+lc[w<<1|1]>=c)//中间段

64     return m-rc[w<<1]+1;

65     return query(c,m+1,r,w<<1|1);

66 }

67 int main()

68 {

69     int i,j,k,n,m,x,d;

70     cin>>n>>m;

71     build(1,n,1);

72     while(m--)

73     {

74         cin>>k;

75         if(k==1)

76         {

77             cin>>x;

78             if(s[1]<x)

79             printf("0\n");

80             else

81             {

82                 int p = query(x,1,n,1);

83                 cout<<p<<endl;

84                 update(p,p+x-1,1,1,n,1);//将这一段更新为已被占

85             }

86         }

87         else

88         {

89             cin>>x>>d;

90             update(x,x+d-1,0,1,n,1);//将这一段更新为空

91         }

92     }

93     return 0;

94 }

 

你可能感兴趣的:(poj)