【BZOJ 1176 2683】Mokia

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.(在2683中,没有S,初始值为0)。

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左上角为(x1,y1),右下角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

保证答案不会超过int范围

分析:

  对操作进行分治,左边的修改必定会影响右边的查询,这一部分只要对x排序,做树状数组就好了。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4
 5 struct A
 6 {
 7     int x, y, pos, ctrl, ans;
 8 } t[200010], q[200010];
 9
10 inline bool cmp(const A &a, const A &b)
11 {
12     return a.pos < b.pos;
13 }
14
15 int s, w, k, x, y, a, b, cnt;
16 int key[2000010], late[2000010], now;
17
18 void modify(int pos, int data)
19 {
20     for ( ; pos <= w + 1; pos += pos & -pos)
21     {
22         if (late[pos] != now) key[pos] = 0;
23         late[pos] = now, key[pos] += data;
24     }
25 }
26
27 int query(int pos)
28 {
29     int ret = 0;
30     for ( ; pos; pos -= pos & -pos)
31         if (late[pos] == now) ret += key[pos];
32     return ret;
33 }
34
35 void cdq(int left, int right)
36 {
37     if (left == right) return;
38     int mid = left + right >> 1;
39     cdq(left, mid); cdq(mid + 1, right);
40     now++;
41     for (int i = mid + 1, j = left; i <= right; i++)
42     {
43         for ( ; j <= mid && q[j].x <= q[i].x; j++)
44             if (q[j].ctrl == 0) modify(q[j].y, q[j].ans);
45         if (q[i].ctrl > 0) q[i].ans += query(q[i].y);
46     }
47     for (int i = left, j = left, k = mid + 1; i <= right; i++)
48     {
49         if ((q[j].x <= q[k].x && j <= mid) || k > right)
50             t[i] = q[j++];
51         else t[i] = q[k++];
52     }
53     memcpy(q + left, t + left, sizeof(q[0]) * (right - left + 1));
54 }
55
56 int main()
57 {
58     scanf("%d%d", &s, &w);
59     while (k != 3)
60     {
61         scanf("%d", &k);
62         if (k == 1)
63         {
64             scanf("%d%d%d", &x, &y, &a);
65             cnt++, q[cnt] = (A) {x + 1, y + 1, cnt, 0, a};
66         }
67         if (k == 2)
68         {
69             scanf("%d%d%d%d", &x, &y, &a, &b);
70             a++, b++;
71             cnt++, q[cnt] = (A) {x, y, cnt, 1, x * y * s};
72             cnt++, q[cnt] = (A) {a, b, cnt, 2, a * b * s};
73             cnt++, q[cnt] = (A) {a, y, cnt, 2, a * y * s};
74             cnt++, q[cnt] = (A) {x, b, cnt, 2, x * b * s};
75         }
76     }
77     cdq(1, cnt);
78     std::sort(q + 1, q + cnt + 1, cmp);
79     for (int i = 1; i <= cnt; i++)
80     {
81         if (q[i].ctrl == 1)
82         {
83             printf("%d\n", q[i].ans + q[i + 1].ans - q[i + 2].ans - q[i + 3].ans);
84         }
85     }
86 }
时间: 2024-11-05 06:09:40

【BZOJ 1176 2683】Mokia的相关文章

【BZOJ 1148】【CTSC 2008】挂缀【BZOJ 1 148】【CTSC 2008】挂缀

[BZOJ 1 148][CTSC 2008]挂缀 这题显然是个贪心,然而我们应该如何贪才能得到最优解= =.... 假设我们按重量升序贪心,那我们可以得到反例(假设在挂缀底部):设有i,j,j<i且W_j<W_i 那么当C_i<W_j,W_i<C_j时,应该选i而不是j 假设我们按拉力升序贪心,依旧可以得到反例(假设在挂缀顶部,S为链以下重量和):设有i,j,j<i,且C_j<C_i 那么当C_i<S+W_j,S+W_i<C_j时,应该先选i当第二高的,而

【BZOJ 1176】 [Balkan2007]Mokia

1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MB Submit: 736  Solved: 306 [Submit][Status] Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下

【BZOJ 1176】【Balkan 2007】Mokia

http://www.lydsy.com/JudgeOnline/problem.php?id=1176 整体二分的例题 把每个询问拆成四个询问,整体二分里x坐标递增,按x坐标扫的时候用树状数组维护y坐标前缀和. 一开始想复杂了,按cdq分治先solve左边再处理中间再solve右边,这样每次都要对x坐标排序,常数巨大,T了好几次TwT 后来参考了别人的代码,发现自己一开始就想复杂了.这道题不需要在solve完后还是保持原来的按x坐标递增的顺序,也不需要先处理出左边的信息才能更新右边的信息. 这

【BZOJ-1176&amp;2683】Mokia&amp;简单题 CDQ分治

1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 821[Submit][Status][Discuss] Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

【BZOJ 4500 矩阵】

Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 390  Solved: 217[Submit][Status][Discuss] Description 有一个n*m的矩阵,初始每个格子的权值都为0,可以对矩阵执行两种操作: 1. 选择一行, 该行每个格子的权值加1或减1. 2. 选择一列, 该列每个格子的权值加1或减1. 现在有K个限制,每个限制为一个三元组(x,y,c),代表格子(x,y)权值等于c.问是否存在一个操作序列,使得操作完后的矩阵满

BZOJ 1176 Balkan 2007 Mokia CDQ分治

题目大意:有一些操作,给一个坐标代表的点加上一个数,和求出一个矩形中的所有数的和. 思路:一眼题,二位树状数组水过. ... .. . 哪里不对?W<=2000000.逗我?这n^2能开下? 这个时候CDQ神牛又来帮助我们了. 这个题应该算是CDQ分治的模板题了吧,简单分析一下,其实不难. 写这个题之前建议写一下BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组这个题,是本题的简化版. 按照正常的解法,我们应该建立一个二位的数据结构,然后分别维护两维的信息.如果用动态开点的线

【BZOJ 2716/2648】 [Violet 3]天使玩偶

2716: [Violet 3]天使玩偶 kd-tree模板题. ①首先依次按照每一维(即先按照x,再按照y,再按照x-多维同理)将点存在一棵二叉树中: 先求出以当前维数为关键字的中间点是谁(用到nth_element这个函数,可以直接把排名为k的放在第k位上,不保证其他有序:nth_element(a+1,a+1+k,a+1+n,cmp)) 为了一会儿查询中求估价函数方便,需要记录一下当前节点的子树中各维的极值(max,min) ②插入操作与splay的插入操作同理. ③询问操作的本质是搜索+

【BZOJ 1056 1862】排名系统

Description 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. Input 第一行是一个整数n(n>=10)表示请求总数目.接下来n行,每行包含了一个请求.请求的具体格式如下: +Name Score 上传最新得分记录.Name表示玩家名字,由大写英文字母组成,不超过10个字符.Score为最多8位的正

【BZOJ1176】Mokia(CDQ分治)

[BZOJ1176]Mokia(CDQ分治) 题面 BZOJ权限题啊,,,, dbzoj真好 Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下三种输入之一(不包含引号): "1 x y a" "2 x1 y1 x2 y2"