[BZOJ1201][HNOI2005]数三角形(树状数组)
2018-02-20 19:47
225 查看
下面定义(i,j)(i,j)表示第ii行的第jj个顶点(共n+1n+1行,第ii行有ii个顶点)
考虑一个朴素的做法:
一、利用递推,预处理出55个值:
(1)lef[i][j]lef[i][j]:(i,j)(i,j)通过未被删除的边,向左延伸的最长距离,如样例中lef[3][3]=0lef[3][3]=0,lef[4][4]=3lef[4][4]=3。
(2)leup[i][j]leup[i][j]:(i,j)(i,j)通过未被删除的边,向左上延伸的最长距离。
(3)riup[i][j]riup[i][j]:(i,j)(i,j)通过未被删除的边,向右上延伸的最长距离。
(4)ledw[i][j]ledw[i][j]:(i,j)(i,j)通过未被删除的边,向左下延伸的最长距离。
(5)ridw[i][j]ridw[i][j]:(i,j)(i,j)通过未被删除的边,向右下延伸的最长距离。
统计正立三角形时,先枚举右下顶点(i,j)(i,j)。容易得出,
右下顶点为(i,j)(i,j)的正立三角形个数不超过min(lef[i][j],leup[i][j])min(lef[i][j],leup[i][j])。
记k=j−min(lef[i][j],leup[i][j])k=j−min(lef[i][j],leup[i][j]),那么第ii行的第[k,j−1][k,j−1]个顶点都有可能成为正立三角形的左下角。
而对于任何的h∈[k,j−1]h∈[k,j−1],(i,h)(i,h)向右上延伸后,能与(i,j)(i,j)构成正立三角形的充分必要条件是:
riup[i][h]≥j−hriup[i][h]≥j−h
统计倒立三角形也一样,先枚举右上顶点(i,j)(i,j),
右上顶点为(i,j)(i,j)的正立三角形个数不超过min(lef[i][j],ledw[i][j])min(lef[i][j],ledw[i][j])。
记k=j−min(lef[i][j],ledw[i][j])k=j−min(lef[i][j],ledw[i][j]),那么第ii行的第[k,j−1][k,j−1]个顶点都有可能成为倒立三角形的左上角。
对于任何的h∈[k,j−1]h∈[k,j−1],(i,h)(i,h)向右下延伸后,能与(i,j)(i,j)构成倒立三角形的充分必要条件是:
ridw[i][h]≥j−hridw[i][h]≥j−h
复杂度是O(n3)O(n3)的。考虑将上面给出的两个不等式移项:
riup[i][h]+h≥jriup[i][h]+h≥j
ridw[i][j]+h≥jridw[i][j]+h≥j
这样就转换成了求一个区间内,有多少个数大于一个定值。将询问离线排序之后,可以使用树状数组解决。复杂度O(n2logn)O(n2logn)。
代码:
考虑一个朴素的做法:
一、利用递推,预处理出55个值:
(1)lef[i][j]lef[i][j]:(i,j)(i,j)通过未被删除的边,向左延伸的最长距离,如样例中lef[3][3]=0lef[3][3]=0,lef[4][4]=3lef[4][4]=3。
(2)leup[i][j]leup[i][j]:(i,j)(i,j)通过未被删除的边,向左上延伸的最长距离。
(3)riup[i][j]riup[i][j]:(i,j)(i,j)通过未被删除的边,向右上延伸的最长距离。
(4)ledw[i][j]ledw[i][j]:(i,j)(i,j)通过未被删除的边,向左下延伸的最长距离。
(5)ridw[i][j]ridw[i][j]:(i,j)(i,j)通过未被删除的边,向右下延伸的最长距离。
统计正立三角形时,先枚举右下顶点(i,j)(i,j)。容易得出,
右下顶点为(i,j)(i,j)的正立三角形个数不超过min(lef[i][j],leup[i][j])min(lef[i][j],leup[i][j])。
记k=j−min(lef[i][j],leup[i][j])k=j−min(lef[i][j],leup[i][j]),那么第ii行的第[k,j−1][k,j−1]个顶点都有可能成为正立三角形的左下角。
而对于任何的h∈[k,j−1]h∈[k,j−1],(i,h)(i,h)向右上延伸后,能与(i,j)(i,j)构成正立三角形的充分必要条件是:
riup[i][h]≥j−hriup[i][h]≥j−h
统计倒立三角形也一样,先枚举右上顶点(i,j)(i,j),
右上顶点为(i,j)(i,j)的正立三角形个数不超过min(lef[i][j],ledw[i][j])min(lef[i][j],ledw[i][j])。
记k=j−min(lef[i][j],ledw[i][j])k=j−min(lef[i][j],ledw[i][j]),那么第ii行的第[k,j−1][k,j−1]个顶点都有可能成为倒立三角形的左上角。
对于任何的h∈[k,j−1]h∈[k,j−1],(i,h)(i,h)向右下延伸后,能与(i,j)(i,j)构成倒立三角形的充分必要条件是:
ridw[i][h]≥j−hridw[i][h]≥j−h
复杂度是O(n3)O(n3)的。考虑将上面给出的两个不等式移项:
riup[i][h]+h≥jriup[i][h]+h≥j
ridw[i][j]+h≥jridw[i][j]+h≥j
这样就转换成了求一个区间内,有多少个数大于一个定值。将询问离线排序之后,可以使用树状数组解决。复杂度O(n2logn)O(n2logn)。
代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } const int N = 1024, M = 4096; int n, led , rid , lef , leu , riu , T[M], tot; ll ans; void change(int x, int v) { for (; x <= 4000; x += x & -x) T[x] += v; } int ask(int x) { int res = 0; for (; x; x -= x & -x) res += T[x]; return res; } struct cyx { int id, ri; cyx() {} cyx(int _id, int _ri) : id(_id), ri(_ri) {} } otz[M]; inline bool comp(const cyx &a, const cyx &b) { return a.ri > b.ri; } int main() { int i, j, x, y, z; n = read(); for (i = 1; i <= n; i++) for (j = 1; j <= i; j++) { x = read(); y = read(); z = read(); lef[i + 1][j + 1] = z; led[i][j] = riu[i + 1][j] = x; rid[i][j] = leu[i + 1][j + 1] = y; } n++; for (i = 1; i <= n; i++) for (j = 1; j <= i; j++) lef[i][j] = lef[i][j] ? lef[i][j - 1] + 1 : 0; for (j = 1; j <= n; j++) for (i = j; i <= n; i++) { leu[i][j] = leu[i][j] ? leu[i - 1][j - 1] + 1 : 0; riu[i][j] = riu[i][j] ? riu[i - 1][j] + 1 : 0; } for (i = n; i; i--) for (j = 1; j <= i; j++) { led[i][j] = led[i][j] ? led[i + 1][j] + 1 : 0; rid[i][j] = rid[i][j] ? rid[i + 1][j + 1] + 1 : 0; } for (i = 1; i <= n; i++) for (j = 1; j <= i; j++) riu[i][j] += j, rid[i][j] += j; for (i = 1; i <= n; i++) { for (j = 0; j <= 4000; j++) T[j] = 0; tot = 0; for (j = 1; j <= i; j++) otz[++tot] = cyx(j, riu[i][j]); sort(otz + 1, otz + tot + 1, comp); int orz = 1; for (j = i; j; j--) { while (orz <= tot && otz[orz].ri >= j) change(otz[orz].id, 1), orz++; ans += ask(j - 1) - ask(j - min(lef[i][j], leu[i][j]) - 1); } for (j = 0; j <= 4000; j++) T[j] = 0; tot = 0; for (j = 1; j <= i; j++) otz[++tot] = cyx(j, rid[i][j]); sort(otz + 1, otz + tot + 1, comp); orz = 1; for (j = i; j; j--) { while (orz <= tot && otz[orz].ri >= j) change(otz[orz].id, 1), orz++; ans += ask(j - 1) - ask(j - min(lef[i][j], led[i][j]) - 1); } } cout << ans << endl; return 0; }
相关文章推荐
- bzoj1201: [HNOI2005]数三角形
- BZOJ 1201: [HNOI2005]数三角形
- 1201: [HNOI2005]数三角形 - BZOJ
- [BZOJ4009][HNOI2015]接水果-整体二分-树状数组-扫描线
- [BZOJ2141]排队(分块+树状数组求逆序对)
- bzoj1199: [HNOI2005]汤姆的游戏
- bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希
- bzoj3289(莫队+树状数组求逆序对)
- 【BZOJ1901】Zju2112 Dynamic Rankings 主席树+树状数组
- 1200: [HNOI2005]木梳 - BZOJ
- 【bzoj1202】[HNOI2005]狡猾的商人
- bzoj1201: [HNOI2005]数三角形----递推+bitset
- [树状数组] BZOJ 4240 有趣的家庭菜园
- bzoj 1200: [HNOI2005]木梳 DP
- BZOJ 4990: [Usaco2017 Feb]Why Did the Cow Cross the Road II 树状数组优化LCS
- 【BZOJ】【P1452】【JSOI2009】【Count】【二维树状数组】
- bzoj 1012: [JSOI2008]最大数maxnumber(树状数组)
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
- bzoj 1452 二维树状数组
- bzoj 4756: [Usaco2017 Jan]Promotion Counting【dfs+树状数组】