• [国家集训队]矩阵乘法


    整体二分+二维数状数组。复杂度 (mathcal O((n^2+Q)log^3n))

    或者不使用二维数状数组,整体二分里面,采用扫描线将修改和询问一起做,这样复杂度可以消去一个 (log)

    #include <bits/stdc++.h>
    using std::sort; using std::unique; using std::lower_bound; using std::vector;
    const int N = 505, M = 60005;
    int n, Q, a[N][N], b[N*N], tot = 0, ans[M];
    struct node { int x, y; };
    vector<node> st[N*N];
    struct Query { int x1, y1, x2, y2, k, id; } q[M], stl[M], str[M];
    #define lowbit(x) (x & (-x))
    int C[N][N];
    void add(int x, int y, int v) {
    	for (int i = x; i <= n; i += lowbit(i))
    		for (int j = y; j <= n; j += lowbit(j))
    			C[i][j] += v;
    }
    int qry(int x, int y) {
    	int ans = 0;
    	for (int i = x; i; i -= lowbit(i))
    		for (int j = y; j; j -= lowbit(j))
    			ans += C[i][j];
    	return ans;
    }
    int query(int x1, int y1, int x2, int y2) {
    	return qry(x2, y2) - qry(x1-1, y2) - qry(x2, y1-1) + qry(x1-1, y1-1);
    }
    void solve(int l, int r, int x, int y) {
    	if (l > r) return;
    	if (x == y) {
    		for (int i = l; i <= r; i++) ans[q[i].id] = b[x];
    		return;
    	}
    	int mid = x+y>>1, totl = 0, totr = 0;
    	for (int i = x; i <= mid; i++)
    		for (int j = 0; j < st[i].size(); j++)
    			add(st[i][j].x, st[i][j].y, 1);
    	for (int i = l; i <= r; i++) {
    		int t = query(q[i].x1, q[i].y1, q[i].x2, q[i].y2);
    		if (t >= q[i].k) {
    			stl[totl++] = q[i];
    		} else {
    			q[i].k -= t;
    			str[totr++] = q[i];
    		}
    	}
    	for (int i = x; i <= mid; i++)
    		for (int j = 0; j < st[i].size(); j++)
    			add(st[i][j].x, st[i][j].y, -1);
    	for (int i = 0; i < totl; i++) q[l+i] = stl[i];
    	for (int i = 0; i < totr; i++) q[l+totl+i] = str[i];
    	solve(l, l+totl-1, x, mid), solve(l+totl, r, mid+1, y);
    }
    int main() {
    	scanf("%d%d", &n, &Q);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			scanf("%d", &a[i][j]), b[++tot] = a[i][j];
    	sort(b+1, b+tot+1); tot = unique(b+1, b+tot+1) - b - 1;
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			st[lower_bound(b+1, b+tot+1, a[i][j]) - b].push_back((node){i, j});
    	for (int i = 1; i <= Q; i++)
    		scanf("%d%d%d%d%d", &q[i].x1, &q[i].y1, &q[i].x2, &q[i].y2, &q[i].k), q[i].id = i;
    	solve(1, Q, 1, tot);
    	for (int i = 1; i <= Q; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    c# 三种取整方法 向上取整 向下取整 四舍五入
    Lambda表达式对DataRow处理
    Dapper数据库字段和model属性映射
    union limit
    北邮五十题
    搜索____深搜 学易错点
    动态规划____有重叠子问题的搜索,都可以转为记忆化搜索
    64位 __int 与 long long写法
    做做 卡特兰数 与 卡米歇尔数
    vector 有点麻烦啊 能简单点么?
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14330714.html
Copyright © 2020-2023  润新知