【CoderForces】#296 Div2 C(线段树+set)
2015-03-18 19:28
323 查看
/* 这边可以用线段树的原因在于,在水平方向上的最大值,与竖直方向上的最大值是相对应的,也就是说我们只需要求出了水平和竖直方向的最大值,然后相乘就可以了, 一开始一直没想通这个,以为是不是对应的,那样的话就没法求了。 线段树思路:两个线段树分别计算出水平方向和竖直方向的最大值,最后相乘就可以了。 这么就涉及到区间的计算,所以需要两个数组来存水平方向和竖直方向的分割线。最后更新就可以了。 也可以用其他的做法。 另外一种方法也是如上求出边界,然后算出间隔,加入到容器当中,最后水平方向和竖直方向最大的相乘就可以了。 */ #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; #define MAX 200002 #define ls rt<<1 #define rs ls|1 #define m (l+r)>>1 int sum1[MAX << 2]; int sum2[MAX << 2]; int col1[MAX << 2]; int col2[MAX << 2]; set<int> posx; set<int> posy; void ups(int *col,int *sum,int rt) { if (col[rt] + 1) { col[ls] = col[rt]; col[rs] = col[rt]; sum[rs] = col[rt]; sum[ls] = col[rt]; col[rt] = -1; } } void uprt( int *sum, int rt) { sum[rt] = max(sum[ls], sum[rs]); } void updata(int *sum, int *col, int L, int R, int c, int l, int r, int rt) { if (L <= l&&r <= R) { col[rt] = c; sum[rt] = c; return; } ups(col, sum, rt); int mid = m; if (L <= mid) updata(sum, col, L, R, c, l, mid, ls); if (mid < R) updata(sum, col, L, R, c, mid + 1, r, rs); uprt(sum, rt); } int main() { int w, h, n; while (~scanf("%d%d%d%*c", &w, &h, &n)) { posx.clear(); posy.clear(); memset(col1, -1, sizeof(col1)); memset(col2, -1, sizeof(col2)); updata(sum1, col1, 0, w, w, 0, w, 1); updata(sum2, col2, 0, h, h, 0, h, 1); posx.insert(0); posx.insert(w); posy.insert(0); posy.insert(h); char str[5]; int a; set<int>::iterator l, r, mid; for (int i = 0; i < n; i++) { scanf("%s%d", str, &a); if (str[0] == 'H') { posy.insert(a); l = posy.find(a); mid = l; l--; r = mid; r++; updata(sum2, col2, *l, *mid, (*mid) - (*l), 0, h, 1); updata(sum2, col2, *mid + 1, *r, *r - *mid, 0, h, 1); } else { posx.insert(a); l = posx.find(a); mid = l; l--; r = mid; r++; updata(sum1, col1, *l, *mid, (*mid) - (*l), 0,w, 1); updata(sum1, col1, *mid + 1, *r, *r - *mid , 0, w, 1); } printf("%lld\n", ((long long)sum1[1]) * sum2[1]); } } }
转载一个别人的其他做法:
/* 这边可以用线段树的原因在于,在水平方向上的最大值,与竖直方向上的最大值是相对应的,也就是说我们只需要求出了水平和竖直方向的最大值,然后相乘就可以了, 一开始一直没想通这个,以为是不是对应的,那样的话就没法求了。 线段树思路:两个线段树分别计算出水平方向和竖直方向的最大值,最后相乘就可以了。 这么就涉及到区间的计算,所以需要两个数组来存水平方向和竖直方向的分割线。最后更新就可以了。 也可以用其他的做法。 */ #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; #define MAX 200002 #define ls rt<<1 #define rs ls|1 #define m (l+r)>>1 int sum1[MAX << 2]; int sum2[MAX << 2]; int col1[MAX << 2]; int col2[MAX << 2]; set<int> posx; set<int> posy; void ups(int *col,int *sum,int rt) { if (col[rt] + 1) { col[ls] = col[rt]; col[rs] = col[rt]; sum[rs] = col[rt]; sum[ls] = col[rt]; col[rt] = -1; } } void uprt( int *sum, int rt) { sum[rt] = max(sum[ls], sum[rs]); } void updata(int *sum, int *col, int L, int R, int c, int l, int r, int rt) { if (L <= l&&r <= R) { col[rt] = c; sum[rt] = c; return; } ups(col, sum, rt); int mid = m; if (L <= mid) updata(sum, col, L, R, c, l, mid, ls); if (mid < R) updata(sum, col, L, R, c, mid + 1, r, rs); uprt(sum, rt); } int main() { int w, h, n; while (~scanf("%d%d%d%*c", &w, &h, &n)) { posx.clear(); posy.clear(); memset(col1, -1, sizeof(col1)); memset(col2, -1, sizeof(col2)); updata(sum1, col1, 0, w, w, 0, w, 1); updata(sum2, col2, 0, h, h, 0, h, 1); posx.insert(0); posx.insert(w); posy.insert(0); posy.insert(h); char str[5]; int a; set<int>::iterator l, r, mid; for (int i = 0; i < n; i++) { scanf("%s%d", str, &a); if (str[0] == 'H') { posy.insert(a); l = posy.find(a); mid = l; l--; r = mid; r++; updata(sum2, col2, *l, *mid, (*mid) - (*l), 0, h, 1); updata(sum2, col2, *mid + 1, *r, *r - *mid, 0, h, 1); } else { posx.insert(a); l = posx.find(a); mid = l; l--; r = mid; r++; updata(sum1, col1, *l, *mid, (*mid) - (*l), 0,w, 1); updata(sum1, col1, *mid + 1, *r, *r - *mid , 0, w, 1); } printf("%lld\n", ((long long)sum1[1]) * sum2[1]); } } }
相关文章推荐
- Codeforces Round #296 (Div. 2)——A.B.C.D
- Codeforces Coder-Strike 2014 (Div. 2) C: Online Meeting 来得最早走得最晚的leader
- Codeforces Round #296 (Div. 2) C(STL_set)
- Coderforces 374 (Div2)
- Codeforces Round #296 (Div. 2) A B C D
- coderforces 218 DIV2
- codeforces round# 296 (div1 D)(bitmasks)
- Codeforces Round #296 (Div. 2) C. Glass Carving
- Codeforces Round #296 (Div. 1) E. Triangles 3000
- Codeforces Coder-Strike 2014 - Finals (online edition, Div. 1)
- coderforces--418 div2 C. An impassioned circulation of affection
- Codeforces Round #225 (Div. 2)A. Coder
- Codeforces Round #227 (Div. 2) E. George and Cards 线段树+set
- Coderforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)
- Codeforces Round #296 (Div. 2) A, B, C, D
- Codeforces Round #296 (Div. 2) —— C(set/multiset)
- Codeforces Round #225 (Div. 2) A.Coder
- 【CoderForce】#296 Div 2 D
- Codeforces Round #296 (Div. 1) E. Triangles 3000
- Codeforces Round #226 (Div. 2 )