Tsinsen A1333: 矩阵乘法(整体二分)

http://www.tsinsen.com/A1333

题意:……

思路:和之前的第k小几乎一样,只不过把一维BIT换成二维BIT而已。注意二维BIT写法QAQ

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <queue>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <stack>
12 using namespace std;
13 #define INF 0x3f3f3f3f
14 #define N 350000
15 typedef long long LL;
16 struct P {
17     int x1, x2, y1, y2, val, id;
18     P () {}
19     P (int x1, int y1, int x2, int y2, int val, int id) : x1(x1), y1(y1), x2(x2), y2(y2), val(val), id(id) {}
20 } q[N], lq[N], rq[N];
21 int bit[505][505], ans[N], n;
22
23 int lowbit(int x) { return x & (-x); }
24
25 void update(int x, int y, int w) {
26     for(int i = x; i <= n; i += lowbit(i))
27         for(int j = y; j <= n; j += lowbit(j)) bit[i][j] += w;
28 }
29
30 int query(int x, int y) {
31     int ans = 0;
32     for(int i = x; i; i -= lowbit(i))
33         for(int j = y; j; j -= lowbit(j)) ans += bit[i][j];
34     return ans;
35 }
36
37 void Solve(int lask, int rask, int l, int r) {
38     if(lask > rask || l > r) return ;
39     if(l == r) {
40         for(int i = lask; i <= rask; i++) if(q[i].id) ans[q[i].id] = l;
41         return ;
42     }
43     int mid = (l + r) >> 1, lcnt = 0, rcnt = 0;
44     for(int i = lask; i <= rask; i++) {
45         if(!q[i].id) {
46             if(q[i].val <= mid) {
47                 update(q[i].x1, q[i].y1, 1);
48                 lq[++lcnt] = q[i];
49             } else rq[++rcnt] = q[i];
50         } else {
51             int num = query(q[i].x2, q[i].y2) - query(q[i].x1 - 1, q[i].y2) - query(q[i].x2, q[i].y1 - 1) + query(q[i].x1 - 1, q[i].y1 - 1);
52             if(num >= q[i].val) lq[++lcnt] = q[i];
53             else {
54                 q[i].val -= num;
55                 rq[++rcnt] = q[i];
56             }
57         }
58     }
59     for(int i = 1; i <= lcnt; i++) if(!lq[i].id) update(lq[i].x1, lq[i].y1, -1);
60     for(int i = 1; i <= lcnt; i++) q[lask+i-1] = lq[i];
61     for(int i = 1; i <= rcnt; i++) q[lask+lcnt+i-1] = rq[i];
62     Solve(lask, lask + lcnt - 1, l, mid);
63     Solve(lask + lcnt, rask, mid + 1, r);
64 }
65
66 int main() {
67     int m, cnt = 0, a;
68     scanf("%d%d", &n, &m);
69     memset(bit, 0, sizeof(bit));
70     for(int i = 1; i <= n; i++)
71         for(int j = 1; j <= n; j++) {
72             scanf("%d", &a); q[++cnt] = P(i, j, 0, 0, a, 0);
73         }
74     for(int i = 1; i <= m; i++) {
75         ++cnt; q[cnt].id = i;
76         scanf("%d%d%d%d%d", &q[cnt].x1, &q[cnt].y1, &q[cnt].x2, &q[cnt].y2, &q[cnt].val);
77     }
78     Solve(1, cnt, 1, INF);
79     for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
80 }
时间: 2024-11-05 11:41:09

Tsinsen A1333: 矩阵乘法(整体二分)的相关文章

tsinsen A1333. 矩阵乘法

题目链接:传送门 题目思路:整体二分(二分的是答案,附带的是操作) 把矩阵中的元素对应成插入操作,然后就有插入和询问操作. 然后根据插入操作对于答案的影响,询问操作所匹配的符合答案个数,将操作分为两段,继续递归... #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring&

BZOJ 2738 矩阵乘法 整体二分+二维树状数组

题目大意:给定一个矩阵,多次求某个子矩阵中的第k小 分块解法见 http://blog.csdn.net/popoqqq/article/details/41356899 <论除最小割外题目解法从来与题目名称无关系列> 整体二分 Solve(x,y,S)表示处理答案在[x,y]区间内的询问集合S 预先将所有数按照大小排序 每次将[1,mid]之间的数插入树状数组 然后对于分治内部的每一个询问 去树状数组中查询相应子矩阵的数值 如果小于等于k就划分到左集合S1 否则划分到右集合S2 然后Solv

【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)

试题来源 2012中国国家集训队命题答辩 问题描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入格式 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N*N个数,表示这个矩阵: 再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角.以(x2,y2)为右下角的子矩形中的第K小数. 输出格式 对于每组询问输出第K小的数. 样例输入 2 2 2 1 3 4 1 2 1 2 1 1 1 2 2 3 样例输出 1

学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67

本文来自:http://www.matrix67.com/blog/archives/tag/poj大牛的博文学习学习 节选如下部分:矩阵乘法的两个重要性质:一,矩阵乘法不满足交换律:二,矩阵乘法满足结合律经典题目1 给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置.操作有平移.缩放.翻转和旋转    这 里的操作是对所有点同时进行的.其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心.如果对每个点分别进行模拟,那么m个操作总共耗时 O(mn).利用矩阵乘法可

十个利用矩阵乘法解决的经典题目

转载自    Matrix67: The Aha Moments 好像目前还没有这方面题目的总结.这几天连续看到四个问这类题目的人,今天在这里简单写一下.这里我们不介绍其它有关矩阵的知识,只介绍矩阵乘法和相关性质.    不要以为数学中的矩阵也是黑色屏幕上不断变化的绿色字符.在数学中,一个矩阵说穿了就是一个二维数组.一个n行m列的矩阵可以乘以一个m行p列的矩阵,得到的结果是一个n行p列的矩阵,其中的第i行第j列位置上的数等于前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应相乘后所有m个

那条矩阵乘法的不归路——数列

话说今天搜矩阵相乘,没有一个人用pascal写,是不是学到矩阵相乘的孩子都果断转c++了...我可是有良心的写博人,当然附上pascal代码 故事开始了 今天看到这样一个题 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1]  (x>3) 求a数列的第n项对1000000007(10^9+7)取余的值. 然后是它的数据范围 对于30%的数据 n<=100: 对于60%的数据 n<=2*10^7: 对于100%的数据 T<=100,n<=2*10^9: 当我

[转]十个利用矩阵乘法解决的经典题目

好像目前还没有这方面题目的总结.这几天连续看到四个问这类题目的人,今天在这里简单写一下.这里我们不介绍其它有关矩阵的知识,只介绍矩阵乘法和相关性质.    不要以为数学中的矩阵也是黑色屏幕上不断变化的绿色字符.在数学中,一个矩阵说穿了就是一个二维数组.一个n行m列的矩阵可以乘以一个m行p列的矩阵,得到的结果是一个n行p列的矩阵,其中的第i行第j列位置上的数等于前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应相乘后所有m个乘积的和.比如,下面的算式表示一个2行2列的矩阵乘以2行3列的矩阵

BZOJ 2738 矩阵乘法(整体二分+二维树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答案的大小进行整体二分,用二维树状数组维护二维区间和, 将超过数量的分治到左区间,不满足的分治到右区间即可. [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std;

【BZOJ 4180】 4180: 字符串计数 (SAM+二分+矩阵乘法)

4180: 字符串计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 164  Solved: 75 Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C', 'D'.现在他要求蒟蒻yts1999构造一个新的字符串S,构造的方法是:进行多次操作,每一次操作选择T的一个子串,将其加入S的末尾. 对于一个可构

POJ 3150 Cellular Automaton(矩阵乘法+二分)

题目链接 题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么. 思路 :下述来自here 首先来看一下Sample里的第一组数据.1 2 2 1 2经过一次变换之后就成了5 5 5 5 4它的原理就是a0 a1 a2 a3 a4->(a4+a0+a1) (a0+a1+a2) (a1+a2+a3) (a2+a3+a4) (a3+a4+a0) 如果用矩阵相乘来描述,那就可以表述为1xN和NxN的矩阵相乘,结果仍为1xN矩阵a