[SDOI2010] 粟粟的书架

给定一个 \(n\times m\) 的矩阵 \(A\)

\(q\) 次询问,每次询问给定 \(x_1\)\(y_1\)\(x_2\)\(y_2\)\(H\),求在子矩阵 \((x_1,y_1)\rightarrow (x_2,y_2)\) 中选择至少多少个元素,才能使所有元素和为 \(H\)

数据范围:
对于前 \(50\%\) 的数据,满足 \(n,m\le200\)\(q\le2\times 10^5\)

对于另外 \(50\%\) 的数据,满足 \(n=1,m\le5\times10^5\)\(m\le 2\times10^4\)

观察数据范围,发现可以拆分为两道问题。

前 50 分

首先显然从大往小选。

考虑二分选的数中的最小数 \(k\),统计给定子矩阵中所有 \(\ge k\) 的数的和 \(S\) 和数量 \(C\)

  • \(S\ge H\),则成立,提高 \(k\)
  • 反之,则降低 \(k\)

单调性:若 \(k\) 增加,合法数减少,\(S\) 降低,所以存在某点 \(k'\) 使得比 \(k'\) 大的答案不合法,小的均合法。

最终答案:\(C-res\),其中 \(res\) 表示多选的 \(k\),即 \(res=\lfloor\cfrac{(S-H)}{k}\rfloor\)

\(S\)\(C\) 通过前缀和维护即可。

namespace Denia1 { // n = 1的情况
	const int maxn = 200;
	const int maxm = 1e3;
	int p[maxn + 5][maxn + 5];
	int pl[maxn + 5][maxn + 5];
	int x[maxn * maxn + 5],xcnt = 0,tot = 0;
	ll sum[maxm + 5][maxn + 5][maxn + 5];
	int cnt[maxm + 5][maxn + 5][maxn + 5];
	ll SUM(int k,int sx,int sy,int ex,int ey) {
		return sum[k][ex][ey] - sum[k][sx - 1][ey] - sum[k][ex][sy - 1] + sum[k][sx - 1][sy - 1];
	}
	ll CNT(int k,int sx,int sy,int ex,int ey) {
		return cnt[k][ex][ey] - cnt[k][sx - 1][ey] - cnt[k][ex][sy - 1] + cnt[k][sx - 1][sy - 1];
	}
	void Main() {
		for (int i = 1;i <= n;i ++) {
			for (int j = 1;j <= m;j ++) {
				cin >> p[i][j];
				x[++ xcnt] = p[i][j];
			}
		}
		sort(x + 1,x + xcnt + 1);
		tot = unique(x + 1,x + xcnt + 1) - x - 1;
		for (int i = 1;i <= n;i ++) for (int j = 1;j <= m;j ++) pl[i][j] = lower_bound(x + 1,x + tot + 1,p[i][j]) - x;
		for (int k = 0;k <= tot;k ++) {
			for (int i = 1;i <= n;i ++) {
				for (int j = 1;j <= m;j ++) {
					ll v = 0ll; int c = 0;
					if (pl[i][j] >= k) v = p[i][j],c = 1;
					sum[k][i][j] = v + sum[k][i - 1][j] + sum[k][i][j - 1] - sum[k][i - 1][j - 1];
					cnt[k][i][j] = c + cnt[k][i - 1][j] + cnt[k][i][j - 1] - cnt[k][i - 1][j - 1];
				}
			}
		}
		while (q --) {
			int sx,sy,ex,ey; ll h; cin >> sx >> sy >> ex >> ey >> h;
			int L = 0,R = tot,ans = 0;
			while (L <= R) {
				int mid = (L + R) >> 1;
				if (SUM(mid,sx,sy,ex,ey) >= h) L = mid + 1,ans = mid;
				else R = mid - 1;
			}
			ll v = SUM(ans,sx,sy,ex,ey);
			if (v < h) cout << "Poor QLW\n";
			else {
				int c = CNT(ans,sx,sy,ex,ey);
				int fl = 0;
				if (x[ans] != 0) fl = (v - h) / x[ans];
				cout << c - fl << "\n";
			}		
		}
	}
}

后 50 分

套主席树板子 + 线段树二分。

namespace Denia2 { // n = 1的情况
	const int maxn = 5e5;
	int p[maxn + 5];
	int pl[maxn + 5],tot = 0;
	struct PST {
		#define ls(x) (tr[x].ls)
		#define rs(x) (tr[x].rs)
		struct node {
			int ls,rs;
			ll sum;
			int cnt;
		};
		int root[maxn + 5];
		node tr[40 * maxn + 5]; int nodecnt = 0;
		int build(int l,int r) {
			int u = ++ nodecnt;
			if (l == r) return u;
			int mid = (l + r) >> 1;
			ls(u) = build(l,mid);
			rs(u) = build(mid + 1,r);
			return u;
		}
		int insert(int rt,int l,int r,int p,ll v) {
			int u = ++ nodecnt;
			tr[u] = tr[rt];
			if (l == r) return tr[u].sum += v,tr[u].cnt ++,u;
			int mid = (l + r) >> 1;
			if (p <= mid) ls(u) = insert(ls(u),l,mid,p,v);
			else rs(u) = insert(rs(u),mid + 1,r,p,v);
			tr[u].sum = tr[ls(u)].sum + tr[rs(u)].sum;
			tr[u].cnt = tr[ls(u)].cnt + tr[rs(u)].cnt;
			return u;
		}
		// 查询和>=qs的最少元素数量
		int query(int u,int v,int l,int r,ll qs) {
			if (l == r) return (qs + pl[l] - 1) / pl[l];
			int mid = (l + r) >> 1;
			ll rsum = (tr[rs(v)].sum - tr[rs(u)].sum);
			if (qs <= rsum) return query(rs(u),rs(v),mid + 1,r,qs);
			return query(ls(u),ls(v),l,mid,qs - rsum) + tr[rs(v)].cnt - tr[rs(u)].cnt;
		}
	};
	PST pst;
	void Main() {
		for (int i = 1;i <= m;i ++) cin >> p[i],pl[i] = p[i];
		sort(pl + 1,pl + m + 1);
		tot = unique(pl + 1,pl + m + 1) - pl - 1;
		for (int i = 1;i <= m;i ++) p[i] = lower_bound(pl + 1,pl + tot + 1,p[i]) - pl;
		pst.root[0] = pst.build(1,tot);
		for (int i = 1;i <= m;i ++) pst.root[i] = pst.insert(pst.root[i - 1],1,tot,p[i],pl[p[i]]);
		while (q --) {
			int x1,l,x2,r; ll h; cin >> x1 >> l >> x2 >> r >> h;
			ll sums = pst.tr[pst.root[r]].sum - pst.tr[pst.root[l - 1]].sum;
			if (sums < h) cout << "Poor QLW\n";
			else cout << pst.query(pst.root[l - 1],pst.root[r],1,tot,h) << "\n";
		}
	}
}

posted @ 2026-08-30 09:52  Denia-kawaii  阅读(4)  评论(0)    收藏  举报