全局二分的经典题。


最初试图用持久化线段树和分块,然后欢快地tle+mle了。看到jason_yu和mhy过了,只能说自己的常数优化还不过关啊。


第一次写这种二分。就是把所有东西扔进来快速排序,顺便考虑每个询问应该被扔到哪边。然后加树状数组来统计就好了。


代码巨丑。


#include <cstdio>

#include <cctype>

#include <cstring>

#include <algorithm>


using namespace std;


struct query {

int x1, y1, x2, y2, k, n;

};


int _d_;

#define readInt(_x_) { \

int& _s_ = _x_; \

while (!isdigit(_d_ = getchar())); \

_s_ = 0; \

while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar())); \

}


const int maxn = 509;

const int maxq = 310009;


int n, m, t, maxa, a[maxn][maxn], b[maxn][maxn], ttm;

int d[maxn * maxn], ans[maxq], tdr[maxq];

query q[maxq];


void btChg(int x, int y, int v) {

for (int p = x; p <= n; p += (p & -p))

for (int q = y; q <= n; q += (q & -q))

if (b[p][q] ^ ttm) { 

a[p][q] = v;

b[p][q] = ttm;

}

else

a[p][q] += v;

}


int btQry(int x, int y) {

int s = 0;

for (int p = x; p; p -= (p & -p))

for (int q = y; q; q -= (q & -q))

if (b[p][q] == ttm)

s += a[p][q];

return s;

}


void qSort(int vl, int vr, int ql, int qr) {

if (vl == vr) {

for (int i = ql; i <= qr; ++ i)

if (q[i]. n > -1)

ans[q[i]. n] = d[vl];

}

else {

++ ttm;

int vm = (vl + vr) >> 1;

for (int i = ql; i <= qr; ++ i)

if (q[i]. n == -1) {

if (q[i]. k <= d[vm]) {

btChg(q[i]. x1, q[i]. y1, 1);

tdr[i] = 0;

}

else

tdr[i] = 1;

}

for (int i = ql; i <= qr; ++ i)

if (q[i]. n > -1) {

int g = btQry(q[i]. x2, q[i]. y2) + btQry(q[i]. x1, q[i]. y1)

   - btQry(q[i]. x1, q[i]. y2) - btQry(q[i]. x2, q[i]. y1);

if (g < q[i]. k) {

q[i]. k -= g;

tdr[i] = 1;

}

else

tdr[i] = 0;

}

int i = ql, j = qr;

while (i < j) {

for (; i < j && tdr[i] == 0; ++ i);

for (; i < j && tdr[j] == 1; -- j);

if (i <= j) {

swap(q[i], q[j]);

swap(tdr[i], tdr[j]);

++ i;

-- j;

}

}

for (i = ql - 1; i < qr && tdr[i + 1] == 0; ++ i);

if (ql <= i)

qSort(vl, vm, ql, i);

if (i + 1 <= qr)

qSort(vm + 1, vr, i + 1, qr);

}

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


memset(a, 0, sizeof(a));

memset(b, 0, sizeof(b));

ttm = 0;

readInt(n);

readInt(m);

t = 0;

maxa = 0;

for (int i = 1; i <= n; ++ i)

for (int j = 1; j <= n; ++ j) {

readInt(q[t]. k);

if (q[t]. k > maxa)

maxa = q[t]. k;

d[i * n + j - n - 1] = q[t]. k;

q[t]. x1 = i;

q[t]. y1 = j;

q[t]. n = -1;

++ t;

}

sort(d, d + n * n);

for (int i = 0; i < m; ++ i) {

readInt(q[t]. x1);

-- q[t]. x1;

readInt(q[t]. y1);

-- q[t]. y1;

readInt(q[t]. x2);

readInt(q[t]. y2);

readInt(q[t]. k);

q[t]. n = i;

++ t;

}

qSort(0, n * n - 1, 0, t - 1);

for (int i = 0; i < m; ++ i)

printf("%d\n", ans[i]);

}