Uva7716 The Cure(CDQ分治 + 整体二分)
2018-02-11 14:52
232 查看
/** Uva7716 The Cure 题意: 给一个n * n的矩阵,有q个查询,每次查询r,c,s,k表示已(r,c)为右上角 大小为s的正方形中 第k小的元素 思路:可用CDQ分治, 二分所有值的答案, 对于答案在[L, R]的矩阵,将[L, mid]的矩阵用1填充,查询满足条件的 放进[L, mid]递归处理, 不满足条件的放进[mid, R]中去处理 */ #include<bits/stdc++.h> const int maxn = 260; const int maxq = 2e5 + 5e4 + 10; const int INF = 1e9 + 10; using namespace std; struct query { int x1, x2, y1, y2, k; void input() { scanf("%d %d %d %d", &x1, &y1, &x2, &k); y2 = y1 + x2 - 1; x2 = x1 + x2 - 1; } } res[maxq]; typedef struct point { int x, y, val; point() {} point(int x, int y, int v) : x(x), y(y), val(v) {} } operation; int n, m, kase = 1, T, q; int mat[maxn][maxn]; point point_val[maxn * maxn]; operation opt[4 * maxq + maxn * maxn]; int s[maxq], can[maxq], notcan[maxq]; int tot, rec[maxq], C[maxn]; int b[maxn * maxn], all, cnt; int py[maxn * maxn + maxq * 2]; map<int, int> idx_first, idx_last; bool cmp1(point p1, point p2) { if(p1.x != p2.x) return p1.x < p2.x; if(p1.y != p2.y) return p1.y < p2.y; return p1.val > p2.val; } bool cmp2(point p1, point p2) { return p1.val < p2.val; } void update(int x, int data, int tal) { for( ; x <= tal; x += x & -x) C[x] += data; } int get_sum(int x) { int ans = 0; for(; x; x -= x & -x) ans += C[x]; return ans; } void solve(int l, int r, int from, int to) { if(from == to) return ; int mid = (l + r) >> 1, v1 = b[l], v2 = b[mid]; int id1 = idx_first[v1], id2 = idx_last[v2]; int num = 0, t1 = 0, t2 = 0, now = from, toty = 0, it = 0; for(int i = id1; i <= id2; i++) { opt[num++] = point(point_val[i].x, point_val[i].y, 1); py[toty++] = point_val[i].y; } for(int i = from; i < to; i++) { int ix = s[i]; opt[num++] = point(res[ix].x1 - 1, res[ix].y1 - 1, 0); opt[num++] = point(res[ix].x2, res[ix].y1 - 1, 0); opt[num++] = point(res[ix].x1 - 1, res[ix].y2, 0); opt[num++] = point(res[ix].x2, res[ix].y2, 0); py[toty++] = res[ix].y1 - 1; py[toty++] = res[ix].y2; } sort(opt, opt + num, cmp1); sort(py, py + toty); toty = unique(py, py + toty) - py; for(int i = 1; i <= toty; i++) C[i] = 0; for(int i = 0; i < num; i++) { int ind = upper_bound(py, py + toty, opt[i].y) - py; if(opt[i].val) update(ind, 1, toty); else mat[opt[i].x][opt[i].y] = get_sum(ind); } for(int i = from; i < to; i++) { int ix = s[i]; query p = res[ix]; int x = p.x1 - 1, y = p.y1 - 1, X = p.x2, Y = p.y2; int tal = mat[X][Y] - mat[x][Y] - mat[X][y] + mat[x][y]; if(tal >= p.k) { rec[ix] = min(rec[ix], v2); can[t1++] = ix; } else { notcan[t2++] = ix; res[ix].k -= tal; } } for(int i = 0; i < t1; i++) s[now++] = can[i]; for(int i = 0; i < t2; i++) s[now++] = notcan[i]; if(l != r) solve(mid + 1, r, from + t1, to); if(l == r) return ; solve(l, mid, from, from + t1); } int main() { while(scanf("%d", &n) != EOF) { cnt = all = 0; idx_first.clear(); idx_last.clear(); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &mat[i][j]); point_val[cnt++] = point(i, j, mat[i][j]); b[all++] = mat[i][j]; mat[i][j] = 0; } } sort(point_val, point_val + cnt, cmp2); sort(b, b + all); all = unique(b, b + all) - b; for(int i = 0; i < cnt; i++) { int val = point_val[i].val; if(!idx_first.count(val)) idx_first[val] = i; idx_last[val] = i; } scanf("%d", &q); for(int i = 1; i <= q; i++) { res[i].input(); s[i] = i; rec[i] = INF; } solve(0, all - 1, 1, q + 1); for(int i = 1; i <= q; i++) printf("%d\n", rec[i]); } return 0; }
相关文章推荐
- 【cdq分治】cdq分治与整体二分学习笔记Part2.cdq分治
- HDU - 5618 Jam's problem again(cdq分治和整体二分)
- HDU 5412 CRB and Queries 求区间第k小 CDQ分治+整体二分
- CDQ分治与整体二分小结
- 整体二分\cdq分治——洛谷P3332 [ZJOI2013]K大数查询
- HDU 5412 CRB and Queries(整体二分 | CDQ分治)
- [CDQ分治与整体二分]个人对CDQ分治与整体二分的理解
- 2017 暑假艾教集训 day9(整体二分 + cdq分治 cdq真是我女神!!!)
- 主席树+CDQ分治+整体二分
- CDQ分治与整体二分小结
- [BZOJ3110][ZJOI2013]K大数查询-CDQ分治-整体二分
- 整体二分&CDQ分治:[BZOJ2527][POI2011] meteors [BZOJ3295][CQOI2011] 动态逆序对
- cdq分治&整体二分学习缓存
- 【cdq分治】cdq分治与整体二分学习笔记Part1.整体二分
- 整体二分&cdq分治 ZOJ 2112 Dynamic Rankings
- cdq分治和整体二分
- 整体二分&cdq分治的小总结
- cdq分治和整体二分
- 分治挑战数据结构——小记整体二分和CDQ分治
- 整体二分<QAQ> && CDQ分治