区间合并 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两种情况 用一个维护一个区间最长连续和即可
代码君:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
HDU4553
元素有0 1 2三种情况 需要维护两个区间最长连续和
代码君:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }