您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: