BZOJ 2683: 简单题(CDQ分治 + 树状数组)
题意
你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作:
| 命令 | 参数限制 | 内容 |
|---|---|---|
| \(1\ x\ y\ A\) | \(1\le x,y \le N\),A是正整数 | 将格子\(x,y\)里的数字加上\(A\) |
| \(2\ x1\ y1\ x2\ y2\) | \(1\le x1\le x2\le N,1\le y1\le y2\le N\) | 输出\(x1\ y1\ x2\ y2\)这个矩形内的数字和 |
| \(3\) | 无 | 终止程序 |
\(1<=N<=500000\),操作数不超过\(200000\)个,内存限制\(20M\)。
题解
这个题是 cdq分治 的裸题吧。
一维:时间(按输入顺序就行了)
二维:\(x\)坐标(cdq分治)
三维:\(y\)坐标(树状数组)
这个题比较裸,但是cdq分治细节还是有一点的(调的错误我可以列一版了。。)
算法讲解
但我想简单讲一下cdq分治(因为网上很多都很坑没讲清楚)
cdq是专门解决多维偏序的问题,比如像这一道题统计二维矩形的权值,或者直接求高维偏序的个数。
如果不用cdq分治,就只能树套树或者KD-tree这种巨型工业数据结构。而且树套树常常空间和常数都很恐怖,并且很难写……
cdq分治是个比较好写的东西,但其中的思想十分的巧妙和神奇。
你应该学过归并排序求逆序对吧,那是最裸的cdq了。他就是利用了左边的答案来更新右边的答案,cdq就是在这个方面不同于普通的分治。
它每次算答案,只能在右边区间算也就是\([mid+1,r]\)。这是为什么可以这样呢,因为你初始给它的序列,按这样算的话,绝对只会算它原序列左边的贡献,不会算到右边去。(想一想,为什么) 这个只需要自己模拟下分治的区间划分和左右区间考虑就行了。
这就可以会强制使你一开始的那一维有序,对答案计算是正确的。(但切记最后给你的序列不一定是按你给它的顺序了!!!)
然后它中间会有一个排序比较的过程,这就可以使第二个维度变得有序了。(最后的序列一定是第二维度有序的) 然后根据前两个维度算答案就行了,后面的维度全都是附加在这两个维度上面的。
总的步骤:
- 分开(递归计算左区间和右区间)
- 计算(用左区间来统计,右区间来加上贡献)
- 合并(将当前序列变得有序)
又回到题解
这道题,就是对于所有操作进行cdq分治(一般都是对于操作进行分治)。
第三维用树状数组统计\(y\)的前缀和就行了,因为\(x\)已经排好序了,所以可以直接算了。
左区间只执行Add操作,右区间只执行Sum操作。
对于一个询问操作,要将它拆成4个询问操作(就是类似询问二维前缀和),加加减减就行了。
注意几个细节(我调了很久的点)
- 树状数组清空的时候,下标不是
val而是y; - 拆矩阵的时候,一定要不要写错下标;
然后多拍几组,写个暴力很容易查出来的。
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), _end_ = (int)(r); i <= _end_; ++i)
#define Fordown(i, r, l) for(register int i = (r), _end_ = (int)(l); i >= _end_; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar() ) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar() ) x = (x<<1) + (x<<3) + (ch ^ '0');
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("P2683.in", "r", stdin);
freopen ("P2683.out", "w", stdout);
#endif
}
int n;
const int N = 800100;
struct Opt {
int x, y, type, id, val;
inline bool operator < (const Opt &rhs) const {
return (x ^ rhs.x) ? x < rhs.x : type < rhs.type;
}
};
Opt lt[N], tmp[N];
#define lowbit(x) (x & -(x))
struct Fenwick_Tree {
int c[500100];
inline void Add(int pos, int val) { for (; pos <= n; pos += lowbit(pos) ) c[pos] += val; }
inline int Sum(int pos) { int res = 0; for (; pos; pos -= lowbit(pos) ) res += c[pos]; return res; }
inline void Clear(int pos) { for (; pos <= n; pos += lowbit(pos) ) if (c[pos]) c[pos] = 0; else break; }
};
Fenwick_Tree T;
int ans[N];
void Cdq(int l, int r) {
if (l == r) return ;
int mid = (l + r) >> 1;
Cdq(l, mid); Cdq(mid + 1, r);
int lp = l, rp = mid + 1, o = l;
while (lp <= mid && rp <= r) {
if (lt[lp] < lt[rp]) {
if (lt[lp].type == 1) T.Add(lt[lp].y, lt[lp].val);
tmp[o ++] = lt[lp ++];
} else {
if (lt[rp].type == 2) ans[lt[rp].id] += lt[rp].val * T.Sum(lt[rp].y);
tmp[o ++] = lt[rp ++];
}
}
while (lp <= mid) tmp[o ++] = lt[lp ++];
while (rp <= r) {
if (lt[rp].type == 2) ans[lt[rp].id] += lt[rp].val * T.Sum(lt[rp].y);
tmp[o ++] = lt[rp ++];
}
For (i, l, mid) if (lt[i].type == 1) T.Clear(lt[i].y);
For (i, l, r) lt[i] = tmp[i];
}
int qcnt, acnt;
inline void Addq(int x, int y, int type, int id, int val) {
lt[++qcnt] = (Opt){x, y, type, id, val};
}
int main () {
File() ;
n = read();
for (;;) {
int opt = read();
if (opt == 3) break ;
int xa, ya, xb, yb, val;
if (opt == 1) {
xa = read(); ya = read(); val = read();
Addq(xa, ya, 1, 0, val);
} else {
xa = read(); ya = read();
xb = read(); yb = read();
Addq(xa - 1, ya - 1, 2, (++ acnt), 1);
Addq(xa - 1, yb, 2, acnt, -1);
Addq(xb, ya - 1, 2, acnt, -1);
Addq(xb, yb, 2, acnt, 1);
}
}
Cdq(1, qcnt);
For (i, 1, acnt) printf ("%d\n", ans[i]);
return 0;
}
BZOJ 2683: 简单题(CDQ分治 + 树状数组)的更多相关文章
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
- BZOJ2683: 简单题(cdq分治 树状数组)
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 2142 Solved: 874[Submit][Status][Discuss] Descripti ...
- 【bzoj1176】[Balkan2007]Mokia/【bzoj2683】简单题 CDQ分治+树状数组
bzoj1176 题目描述 维护一个W*W的矩阵,初始值均为S(题目描述有误,这里的S没有任何作用!).每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数 ...
- BZOJ 2683: 简单题(CDQ 分治)
题面 Time Limit: 50 Sec Memory Limit: 128 MB Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: ...
- BZOJ 2683 简单题 ——CDQ分治
[题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...
- BZOJ 1176: [Balkan2007]Mokia( CDQ分治 + 树状数组 )
考虑cdq分治, 对于[l, r)递归[l, m), [m, r); 然后计算[l, m)的操作对[m, r)中询问的影响就可以了. 具体就是差分答案+排序+离散化然后树状数组维护.操作数为M的话时间 ...
- BZOJ 2683: 简单题 [CDQ分治]
同上题 那你为什么又发一个? 因为我用另一种写法又写了一遍... 不用排序,$CDQ$分治的时候归并排序 快了1000ms... #include <iostream> #include ...
- BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
随机推荐
- PLECS—模型仿真——第十一周作业
1. 直流电机单闭环调速系统比例控制仿真 (1)整体电路图 (2)控制部分电路图 (3)参数设置+仿真结果 2. 直流电机单闭环调速系统比例积分控制仿真 (1)参数设置 (2)仿真结果 3. 直流电机 ...
- youtube视频字幕下载
视频下载 安装TamperMonkey插件 字幕下载 http://mo.dbxdb.com/setting.html https://zhuwei.me/y2b/
- C# decimal 去掉小数点后的无效0
c#去掉小数点后的无效0 decimal d = 0.0500m; d.ToString("0.##")就出来了 也可以这样 string.Format("{0:0.## ...
- 小技巧:selenium java中如何使用chrome默认的profile
使用浏览器默认的profile可以在一定程度上实现免登录的效果,另外默认的profile中很多文件都被缓存了,也有利于加快测试的速度 System.setProperty("webdrive ...
- spring 组件自动装载示例(@ComponentScan,@Component,@Scope)
今天学习spring的bean组件装载功能,个人不太喜欢xml文件一个个配置bean的方式,所以主要学习测试注解式的自动装载方式.下面将简单说明下@Component的用法,简单入门示例献给大家. ...
- Entity Framework——配置文件设置
可以使用配置文件或代码(EF6起)配置EF框架. 一.使用配置文件 安装Entity Framework自动生成的配置 当使用VS的NuGet自动安装Entity Framework(本文使用6.2. ...
- C#语言Devdevexpress控件chart在C/S框架中的使用
声明.数据库连接机制框架已经写好.框架模式是MVC模式.就以我的from测试.我的做法是在查询页面创建一个按钮,然后在这个按钮上绑定一个点击事件.点击查询按钮把查询条件传到需要显示图例的页面.查询页面 ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- SpringBoot整合SpringSecurity,SESSION 并发管理,同账号只允许登录一次
重写了UsernamePasswordAuthenticationFilter,里面继承AbstractAuthenticationProcessingFilter,这个类里面的session认证策略 ...
- 排序算法java实现
1. 插入排序 原理:遍历到第N个元素的时候前面的N-1个元素已经是排序好的了,那么就查找前面的N-1个元素把这第N个元素放在合适的位置,如此下去直到遍历完序列的元素为止. 算法的复杂度也是简单 ...