http://www.lydsy.com/JudgeOnline/problem.php?id=1176

分治的例题

把每个询问拆成四个询问,整体二分里x坐标递增,按x坐标扫的时候用树状数组维护y坐标前缀和。

一开始想复杂了,按cdq分治先solve左边再处理中间再solve右边,这样每次都要对x坐标排序,常数巨大,T了好几次TwT

后来参考了别人的代码,发现自己一开始就想复杂了。这道题不需要在solve完后还是保持原来的按x坐标递增的顺序,也不需要先处理出左边的信息才能更新右边的信息。

这样直接分治啊~~~~~处理完一大块左边对右边的贡献再递归处理左右两块。只要一开始对x坐标排序即可,solve的过程从整到散,不需要再进行排序。

一开始还忘了离散化,每次清空树状数组都用memsetヽ(*´Д`*)ノ后来发现从前往后扫一遍把原先加的减回去会快得多。

时间复杂度$O(mlogmlogw)$,m的含义为所有修改和询问的数量,w的含义为离散化y坐标后的y坐标最大值,即树状数组的上界。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define lowbit(x) (x&(-x))
using namespace std;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct node {
int op, x, y, a, id, pos;
bool operator < (const node &A) const {
return x == A.x ? (y == A.y ? pos < A.pos : y < A.y) : x < A.x;
}
} Q[200003], q[200003]; int s, w, m = 0, ans[40003]; namespace CDQ {
int bits[180003];
void update(int x, int num) {
for(; x <= w; x += lowbit(x)) bits[x] += num;
}
int Qsum(int x) {
int ret = 0;
for(; x; x -= lowbit(x)) ret += bits[x];
return ret;
} void solve(int l, int r) {
if (l == r) return;
int mid = (l + r) >> 1;
for(int i = l; i <= r; ++i) {
if (Q[i].op == 1 && Q[i].id <= mid) update(Q[i].y, Q[i].a);
if (Q[i].op == 2 && Q[i].id > mid) ans[Q[i].pos] += Q[i].a * Qsum(Q[i].y);
} for(int i = l; i <= r; ++i)
if (Q[i].op == 1 && Q[i].id <= mid) update(Q[i].y, -Q[i].a); int tl = l, tr = mid + 1;
for(int i = l; i <= r; ++i)
if (Q[i].id <= mid) q[tl++] = Q[i];
else q[tr++] = Q[i];
for(int i = l; i <= r; ++i) Q[i] = q[i]; solve(l, mid);
solve(mid + 1, r);
}
} int H[180003], cnt = 0, anscnt = 0;
int main() {
s = in(); w = in(); int x1, y1, x2, y2;
for(int x = in(); x != 3; x = in())
if (x == 1) {
Q[++m].op = 1;
Q[m].x = in(); Q[m].y = in(); Q[m].a = in(); Q[m].id = m; Q[m].pos = 0;
H[++cnt] = Q[m].y;
} else {
x1 = in(); y1 = in(); x2 = in(); y2 = in();
H[++cnt] = y1 - 1; H[++cnt] = y2;
ans[++anscnt] = s * (x2 - x1 + 1) * (y2 - y1 + 1);
++m; Q[m] = (node) {2, x1 - 1, y1 - 1, 1, m, anscnt};
++m; Q[m] = (node) {2, x1 - 1, y2, -1, m, anscnt};
++m; Q[m] = (node) {2, x2, y1 - 1, -1, m, anscnt};
++m; Q[m] = (node) {2, x2, y2, 1, m, anscnt};
} sort(H + 1, H + cnt + 1);
cnt = unique(H + 1, H + cnt + 1) - H;
w = cnt - 1; for(int i = 1; i <= m; ++i) Q[i].y = lower_bound(H + 1, H + cnt, Q[i].y) - H; sort(Q + 1, Q + m + 1); CDQ::solve(1, m); for(int i = 1; i <= anscnt; ++i) printf("%d\n", ans[i]); return 0;
}

一定要想好了再码!

【BZOJ 1176】【Balkan 2007】Mokia的更多相关文章

  1. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  2. 【BZOJ】3319: 黑白树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...

  3. 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...

  4. 【BZOJ】【2084】【POI2010】Antisymmetry

    Manacher算法 啊……Manacher修改一下就好啦~蛮水的…… Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233) 长度为奇数的肯定不 ...

  5. 【BZOJ】1013: [JSOI2008]球形空间产生器sphere

    [BZOJ]1013: [JSOI2008]球形空间产生器sphere 题意:给n+1个n维的点的坐标,要你求出一个到这n+1个点距离相等的点的坐标: 思路:高斯消元即第i个点和第i+1个点处理出一个 ...

  6. 【BZOJ】1002:轮状病毒(基尔霍夫矩阵【附公式推导】或打表)

    Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图 ...

  7. 【BZOJ】【3083】遥远的国度

    树链剖分/dfs序 其实过了[BZOJ][4034][HAOI2015]T2以后就好搞了…… 链修改+子树查询+换根 其实静态树的换根直接树链剖分就可以搞了…… 因为其实只有一样变了:子树 如果roo ...

  8. 【BZOJ】【2434】【NOI2011】阿狸的打字机

    AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...

  9. 【BZOJ】【2738】&【Tsinsen】【A1333】矩阵乘法

    整体二分+树状数组 过了[BZOJ][2527][POI2011]Meteors以后这题就没那么难啦~ 关键是[从小到大]依次插入数字,然后整体二分每个查询的第k大是在第几次插入中被插入的……嗯大概就 ...

随机推荐

  1. [转]基于display:table的CSS布局

    当IE8发布时,它将支持很多新的CSS display属性值,包括与表格相关的属性值:table.table-row和table-cell,它也是最后一款支持这些属性值的主流浏览器.它标志着复杂CSS ...

  2. UESTC 33 Area --凸包面积

    题意: 求一条直线分凸包两边的面积. 解法: 因为题意会说一定穿过,那么不会有直线与某条边重合的情况.我们只要找到一个直线分成的凸包即可,另一个的面积等于总面积减去那个的面积. 怎么得到分成的一个凸包 ...

  3. Android中关于Handler的若干思考

    在之前的博文中,讲过一些和Handler有关的知识,例如: Android 多线程----AsyncTask异步任务详解 Android多线程----异步消息处理机制之Handler详解 今天再把Ha ...

  4. 异常总结<经典例题>

    public class Test1 { public static void main(String[] args) { try { add(1); System.out.println(" ...

  5. NVIDIA显卡设置

    在玩3D游戏时,因为我的显卡不是特别给力,所以针对性能做出牺牲质量换取性能的调整. 简单设置 简单的方法是,3D设置-通过预览调整图像设置,根据偏重点来设置平衡:性能或者质量. 高级设置 如果你想自行 ...

  6. C语言:联合变量

    #include <stdio.h> union hold{ int digit; double big; char letter; }; int main(){ union hold a ...

  7. tween.js

     简要教程 tween.js是一款可生成平滑动画效果的js动画库.相关的动画库插件还有:snabbt.js 强大的jQuery动画库插件和Tweene-超级强大的jQuery动画代理插件. tween ...

  8. GNU Trove trove4j

    GNU Trove (http://trove4j.sourceforge.net/) 是一个Java 集合类库.在某些场景下,Trove集合类库提供了更好的性能,而且内存使用更少.以下是Trove中 ...

  9. BZOJ 1251: 序列终结者

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 3773  Solved: 1579 [Submit][Status][Dis ...

  10. Easyui Tree方法扩展 - getLevel(获取节点级别)

    Easyui Tree一直就没有提供这个方法,以前没有用到,所以一直没怎么在意,这次自己用到了,顺便扩展了一个方法,分享给大家. $.extend($.fn.tree.methods, { getLe ...