区间合并 POJ3667+HDU4553

两道题都是线段树的区间合并

lsum, rsum分别表示左/右端点 开始向右/左 符合条件的元素的最长连续长度

sum表示这个区间的符合条件的元素的最长连续长度

所以pushUp可写: 

 1 void pushUp(int root, int l, int r)
 2 {
 3     int len = r - l + 1;
 4     int lenr = len >> 1, lenl = len - lenr;
 5     lsum[root] = lsum[lson];
 6     rsum[root] = rsum[rson];
 7     if (lsum[root] == lenl) lsum[root] += lsum[rson];
 8     if (rsum[root] == lenr) rsum[root] += rsum[lson];
 9     sum[root] = max(rsum[lson]+lsum[rson], max(sum[lson], sum[rson])); 
10 }

更新时 根据更新的元素的值 可以确定 这个区间的sum lsum 和 rsum 是len 还是 0

所以pushDown 和 update可以写了

这里放pushDown

 1 void pushDown(int root, int l, int r)
 2 {
 3     int len = r - l + 1;
 4     int lenr = len >> 1, lenl = len - lenr;
 5     if (setmark[root] != -1)
 6     {
 7         int v = setmark[root];
 8         setmark[lson] = setmark[rson] = v;
 9         setmark[root] = -1; 
10         lsum[lson] = rsum[lson] = sum[lson] = v ? 0 : lenl;//被占用是1 不被占用是0
11         lsum[rson] = rsum[rson] = sum[rson] = v ? 0 : lenr;
12     }
13 }

另外注意的是query的方式

1 int query(int root, int l, int r, int qlen)
2 {
3     if (l == r) return l;
4     pushDown(root, l, r);
5     int mid = (l+r) >> 1;
6     if (sum[lson] >= qlen) return query(lson, l, mid, qlen);
7     else if (rsum[lson]+lsum[rson] >= qlen) return mid-rsum[lson]+1;//左区间的右半部份 和右区间的左半部份 
8     else if return query(rson, mid+1, r, qlen);
9 }

如果不存在直接求sum[1]是否>=qlen

POJ3667

元素只有1 和 0两种情况 用一个维护一个区间最长连续和即可

代码君:

  1 #include <string.h>
  2 #include <stdio.h>
  3 #include <algorithm>
  4 #include <iostream>
  5 #define lson root<<1
  6 #define rson root<<1|1
  7 #define fi first
  8 #define se second
  9 #define pb push_back
 10 #define po pop_back
 11 
 12 typedef long long ll;
 13 
 14 const int MAXN = 50007;
 15 const int MAXM = 50007;
 16 const int INF = 0x3f3f3f3f;
 17 
 18 using namespace std;
 19 
 20 int n, m;
 21 int sum[MAXN << 2];
 22 int setmark[MAXN << 2];
 23 int lsum[MAXN << 2];
 24 int rsum[MAXN << 2];
 25 
 26 void pushUp(int root, int l, int r)
 27 {
 28     int len = r - l + 1;
 29     int lenr = len >> 1, lenl = len - lenr;
 30     lsum[root] = lsum[lson];
 31     rsum[root] = rsum[rson];
 32     if (lsum[root] == lenl) lsum[root] += lsum[rson];
 33     if (rsum[root] == lenr) rsum[root] += rsum[lson];
 34     sum[root] = max(rsum[lson]+lsum[rson], max(sum[lson], sum[rson])); //这个地方 理解!
 35 }
 36 void build(int root, int l, int r)
 37 {
 38     int len = r-l+1;
 39     setmark[root] = -1;
 40     lsum[root] = rsum[root] = sum[root] = len;
 41     if (l == r) return ;
 42     int mid = (l+r) >> 1;
 43     build(lson, l, mid);
 44     build(rson, mid+1, r);
 45     pushUp(root, l, r);
 46 }
 47 void pushDown(int root, int l, int r)
 48 {
 49     int len = r - l + 1;
 50     int lenr = len >> 1, lenl = len - lenr;
 51     if (setmark[root] != -1)
 52     {
 53         int v = setmark[root];
 54         setmark[lson] = setmark[rson] = v;
 55         setmark[root] = -1; 
 56         lsum[lson] = rsum[lson] = sum[lson] = v ? 0 : lenl;//被占用是1 不被占用是0
 57         lsum[rson] = rsum[rson] = sum[rson] = v ? 0 : lenr;
 58     }
 59 }
 60 void update(int root, int l, int r, int ul, int ur, int val)
 61 {
 62     int len = r - l + 1;
 63     int lenr = len >> 1, lenl = len - lenr;
 64     if (l > ur || r < ul) return ;
 65     if (l >= ul && r <= ur)
 66     {
 67         setmark[root] = val;
 68         lsum[root] = rsum[root] = sum[root] = val ? 0 : len;
 69         return ;
 70     }
 71     pushDown(root, l, r);
 72     int mid = (l+r) >> 1;
 73     update(lson, l, mid, ul, ur, val);
 74     update(rson, mid+1, r, ul, ur, val);
 75     pushUp(root, l, r);
 76 }
 77 int query(int root, int l, int r, int qlen)
 78 {
 79     if (l == r) return l;
 80     pushDown(root, l, r);
 81     int mid = (l+r) >> 1;
 82     if (sum[lson] >= qlen) return query(lson, l, mid, qlen);
 83     if (rsum[lson]+lsum[rson] >= qlen) return mid-rsum[lson]+1;//左区间的右半部份 和右区间的左半部份 
 84     if (sum[rson] >= qlen) return query(rson, mid+1, r, qlen);
 85     return -1;
 86 }
 87 int main()
 88 {
 89     //freopen("in.txt", "r", stdin);
 90     while (cin >> n >> m)
 91     {    
 92         build(1, 1, n);
 93         for(int i = 0; i < m; i++)
 94         {
 95             int op, p, l;
 96             scanf("%d", &op);
 97             if (op == 1)
 98             {
 99                 scanf("%d", &l);
100                 if (sum[1] < l) 
101                 {
102                     puts("0");
103                     continue;
104                 }
105                 int pos = query(1, 1, n, l);
106                 cout << pos << endl;    
107                 update(1, 1, n, pos, pos+l-1, 1);
108             }
109             else
110             {
111                 scanf("%d%d", &p, &l);
112                 //cout << p << " " << p+l-1 << endl;
113                 update(1, 1, n, p, p+l-1, 0);
114             }
115         }
116     }
117     return 0;    
118 }
View Code

HDU4553 

元素有0 1 2三种情况 需要维护两个区间最长连续和

代码君:

  1 #include <bits/stdc++.h>
  2 #define lson root<<1
  3 #define rson root<<1|1
  4 #define fi first
  5 #define se second
  6 #define pb push_back
  7 #define po pop_back
  8 
  9 using namespace std;
 10 
 11 typedef long long ll;
 12 typedef pair<int, int> P;
 13 
 14 const int MAXN = 1e5+7;
 15 const int MAXM = 1e5+7;
 16 const int INF = 0x3f3f3f3f;
 17 
 18 
 19 
 20 //0 for diaosi  1 for nvshen
 21 int sum[4][MAXN << 2];
 22 int lsum[4][MAXN << 2];
 23 int rsum[4][MAXN << 2];
 24 int setmark[MAXN << 2];
 25 int pos = -1;
 26 int qlen = -1;
 27 int n, m;
 28 void pushUp(int root, int l, int r, int nu)
 29 {
 30     int len = r-l+1;
 31     int lenr = len >> 1, lenl = len - lenr;
 32     lsum[nu][root] = lsum[nu][lson];
 33     if (lsum[nu][root] == lenl) lsum[nu][root] += lsum[nu][rson];
 34     rsum[nu][root] = rsum[nu][rson];
 35     if (rsum[nu][root] == lenr) rsum[nu][root] += rsum[nu][lson];
 36     sum[nu][root] = max(rsum[nu][lson]+lsum[nu][rson], max(sum[nu][lson], sum[nu][rson])); 
 37 }
 38 void build(int root, int l, int r)
 39 {
 40     int len = r - l + 1;
 41     setmark[root] = -1;
 42     for (int i = 0; i < 2; i++) 
 43     {
 44         sum[i][root] = lsum[i][root] = rsum[i][root] = len;
 45     }
 46     if (l == r) return ;
 47     int mid = (l+r) >> 1;
 48     build(lson, l, mid);
 49     build(rson, mid+1, r);
 50     for (int i = 0; i < 2; i++)
 51     pushUp(root, l, r, i);
 52 }
 53 void pushDown(int root, int l, int r)
 54 {
 55     int len = r - l + 1;
 56     int lenr = len >> 1, lenl = len - lenr;
 57     if (setmark[root] != -1)
 58     {
 59         int val = setmark[root];
 60         setmark[lson] = setmark[rson] = val;
 61         setmark[root] = -1;
 62         lsum[0][lson] = rsum[0][lson] = sum[0][lson] = (val == 0 ? lenl : 0);
 63         lsum[0][rson] = rsum[0][rson] = sum[0][rson] = (val == 0 ? lenr : 0);
 64         lsum[1][lson] = rsum[1][lson] = sum[1][lson] = ( (val == 0 || val == 1) ? lenl : 0);  
 65         lsum[1][rson] = rsum[1][rson] = sum[1][rson] = ( (val == 0 || val == 1) ? lenr : 0);
 66     }
 67 }
 68 void update(int root, int l, int r, int ul, int ur, int val)
 69 {
 70     int len = r - l + 1;
 71     if (l > ur || r < ul) return;
 72     if (l >= ul && r <= ur)
 73     {
 74         setmark[root] = val;
 75         lsum[0][root] = rsum[0][root] = sum[0][root] = (val == 0 ? len : 0);
 76         lsum[1][root] = rsum[1][root] = sum[1][root] = ((val == 0 || val == 1) ? len : 0);
 77         return ;
 78     }
 79     pushDown(root, l, r);
 80     int mid = (l+r) >> 1;
 81     update(lson, l, mid, ul, ur, val);
 82     update(rson, mid+1, r, ul, ur, val);
 83     for (int i = 0; i < 2; i++)
 84     pushUp(root, l, r, i);
 85 }
 86 
 87 int query(int root, int l, int r, int qlen, int nu)
 88 {
 89     if (l == r)    return l;
 90     pushDown(root, l, r);
 91     int mid = (l+r) >> 1;
 92     if (sum[nu][lson] >= qlen) return query(lson, l, mid, qlen, nu);
 93     else if (rsum[nu][lson] + lsum[nu][rson] >= qlen) return mid - rsum[nu][lson] + 1; 
 94     else return query(rson, mid+1, r, qlen, nu);
 95 }
 96 int main()
 97 {
 98     //注意都是英文符号
 99     //freopen("in.txt", "r", stdin);
100     int T;
101     scanf("%d", &T);
102     for (int cas = 1; cas <= T; cas++)
103     {
104         printf("Case %d:\n", cas);
105         scanf("%d%d", &n, &m);
106         build(1, 1, n);
107         for (int i = 0; i < m; i++)
108         {
109             char buf[32];
110             int qlen;
111             scanf("%s", buf);
112             if (buf[0] == 'D')
113             {
114                 scanf("%d", &qlen);
115                 int pos = -1;
116                 if (qlen > n || sum[0][1] < qlen) 
117                 {
118                     puts("fly with yourself");
119                     continue;    
120                 }
121                 pos = query(1, 1, n, qlen, 0);
122                 printf("%d,let's fly\n", pos);
123                 update(1, 1, n, pos, pos+qlen-1, 1);    
124             }
125             else if (buf[0] == 'N')
126             {
127                 scanf("%d", &qlen);
128                 int pos = -1;
129                 if (qlen > n || sum[1][1] < qlen) 
130                 {
131                     puts("wait for me");
132                     continue;    
133                 }
134                 if (sum[0][1] >= qlen) pos = query(1, 1, n, qlen, 0);
135                 else pos = query(1, 1, n, qlen, 1);
136                 printf("%d,don't put my gezi\n", pos);
137                 update(1, 1, n, pos, pos+qlen-1, 2);    
138             }
139             else 
140             {
141                 int l, r;
142                 scanf("%d%d", &l, &r);
143                 update(1, 1, n, l, r, 0);
144                 puts("I am the hope of chinese chengxuyuan!!");
145             }
146         }
147     }
148     return 0;    
149 }
View Code

 

posted @ 2018-04-08 23:23  Lorazepam  阅读(260)  评论(0编辑  收藏  举报