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

在写这题的时候思维非常逗啊。。。。。。。。2333。。。。。。。。。。。。。。。。。。。

最后不得不去看别人的代码。。

噗,,我怎么没想到二维前缀和。。。。。。。。。。。。。。。。。。。。

orz zyf

那么对于一个矩形,我们拆成四个点,那么就可以和add操作一起cdq分治!

orz

cdq分治的话很好想的:

定义$solve(l, r)$表示用l~mid来更新mid+1~r。

考虑如何$O(n)$更新:

首先我们可以先考虑x轴,如果是已经排序好了的话,直接扫过去更新y轴!这点利用了单调的思想。

而如何更新y轴呢?树状数组。

而拆点后如何维护二维前缀和呢?加加减减。

如何快速排序呢?在外边先排序过。

然后完了。

我之前写的cdq非常逗啊,,都没有拆点,直接单调队列暴力扫,但是为啥wa了?我对拍的时候看了一下答案,只有一些答案错了QAQ。。。

一些技巧请看代码,orz

(丧心病狂の加速,我们离散y轴再用bit维护233)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }const int N=170005, M=2000005;int tot, c[M];
inline void add(int x, const int &s) { for(; x<=tot; x+=x&-x) c[x]+=s; }
inline int sum(int x) { int ret=0; for(; x; x-=x&-x) ret+=c[x]; return ret; }int y[N*4], W, n, cnt, ans[N], S;struct dat { int x, y, id, pos, a; bool f; }p[N*5], t[N*5];
inline const bool cmp(const dat &a, const dat &b) { return a.x==b.x ? (a.y==b.y?a.pos<b.pos:a.y<b.y) : a.x<b.x; }void cdq(int l, int r) {if(l==r) return;int mid=(l+r)>>1, l1=l, l2=mid+1;for1(i, l, r) {if(p[i].id<=mid && !p[i].f) add(p[i].y, p[i].a);if(p[i].id>mid && p[i].f) ans[p[i].pos]+=p[i].a*sum(p[i].y);}for1(i, l, r) if(p[i].id<=mid && !p[i].f) add(p[i].y, -p[i].a);for1(i, l, r) if(p[i].id<=mid) t[l1++]=p[i]; else t[l2++]=p[i];for1(i, l, r) p[i]=t[i];cdq(l, mid); cdq(mid+1, r);
}int main() {read(S); read(W);int t=getint();while(t!=3) {if(t==1) { ++n; read(p[n].x); read(p[n].y); read(p[n].a); p[n].f=0; p[n].pos=0; p[n].id=n; y[++tot]=p[n].y; }else {int x1=getint(), y1=getint(), x2=getint(), y2=getint();ans[++cnt]=S*(x2-x1+1)*(y2-y1+1);p[++n].x=x1-1, p[n].y=y1-1, p[n].f=1, p[n].a=1; p[n].id=n; p[n].pos=cnt;p[++n].x=x1-1, p[n].y=y2, p[n].f=1, p[n].a=-1; p[n].id=n; p[n].pos=cnt;p[++n].x=x2, p[n].y=y1-1, p[n].f=1, p[n].a=-1; p[n].id=n; p[n].pos=cnt;p[++n].x=x2, p[n].y=y2, p[n].f=1, p[n].a=1; p[n].id=n; p[n].pos=cnt;y[++tot]=y1; y[++tot]=y2; y[++tot]=y1-1; y[++tot]=y2-1;}read(t);}sort(y+1, y+1+tot); tot=unique(y+1, y+1+tot)-y-1;for1(i, 1, n) p[i].y=lower_bound(y+1, y+1+tot, p[i].y)-y;sort(p+1, p+1+n, cmp);cdq(1, n);for1(i, 1, cnt) printf("%d\n", ans[i]);return 0;
}

  


Description

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

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范围

Source

【BZOJ】1176: [Balkan2007]Mokia(cdq分治)相关推荐

  1. BZOJ 1176: [Balkan2007]Mokia( CDQ分治 + 树状数组 )

    考虑cdq分治, 对于[l, r)递归[l, m), [m, r); 然后计算[l, m)的操作对[m, r)中询问的影响就可以了. 具体就是差分答案+排序+离散化然后树状数组维护.操作数为M的话时间 ...

  2. BZOJ 1176[Balkan2007]Mokia (cdq分治,矩阵加矩阵求和)

    BZOJ 1176[Balkan2007]Mokia (cdq分治,矩阵加矩阵求和) Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值. ...

  3. BZOJ 1176: [Balkan2007]Mokia

    一道CDQ分治的模板题,然而我De了一上午Bug...... 按时间分成左右两半,按x坐标排序然后把y坐标丢到树状数组里,扫一遍遇到左边的就add,遇到右边的query 几个弱智出了bug的点, 一是 ...

  4. cdq分治(bzoj 1176: [Balkan2007]Mokia bzoj 2683: 简单题)

    CDQ分治: 本质:对询问进行分治 优点:和莫队分块一样都属于技巧,关键时刻能免去复杂的数据结构,常数小 缺点:必须离线 参考:http://blog.csdn.net/hbhcy98/article ...

  5. bzoj 1176 Mokia (cdq分治)

    1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MB Submit: 3874  Solved: 1742 [Submit] ...

  6. BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)

    1176: [Balkan2007]Mokia Time Limit: 30 Sec   Memory Limit: 162 MB Submit: 185   Solved: 94 [ Submit] ...

  7. Bzoj 2683: 简单题(CDQ分治)

    2683: 简单题 Time Limit: 50 Sec Memory Limit: 20M. Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两 ...

  8. bzoj 4237: 稻草人(CDQ分治+单调栈+二分)

    4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1352  Solved: 594 [Submit][Status][Discus ...

  9. bzoj 3262: 陌上花开(cdq分治)

    3262: 陌上花开 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 2433  Solved: 1087 [Submit][Status][Disc ...

  10. BZOJ 2961 共点圆 CDQ分治+凸包

    题目大意:给定平面,多次插入点和圆,每次插入点时询问当前插入的点是否在之前插入的所有圆中并且至少在一个圆中 直接用数据结构维护这些点和圆不是很好写,我们考虑CDQ分治 对于每层分治,我们需要对于[mi ...

最新文章

  1. linux 脚本判断一个目录不存在
  2. Bytom BIP-32协议和BIP-44协议解读
  3. Delphi 与 DirectX 之 DelphiX(95): TDIB.x
  4. 怎样快速使用富文本编辑器
  5. LeetCode119.杨辉三角II
  6. 用Java递增Map值的最有效方法–仅搜索一次键
  7. Replication--查看未分发命令和预估所需时间
  8. ORACLE数据库 常用命令和Sql常用语句
  9. python中的常量_深入理解Python中的内置常量
  10. linux系统中英文切换
  11. 简易计算器数码管c语言,简易计算器(数码管显示)
  12. 为什么手机显示系统服务器异常退出游戏,为什么现在进入游戏会提示服务期异常...
  13. c语言scanf用法详解
  14. 交通大数据应用细分_大数据、数据挖掘在交通领域有哪些应用?
  15. 关于如何去实现百度的自动发帖功能猜想
  16. AutoSAR系列讲解(深入篇)13.1-闪烁一颗LED灯 1
  17. 微服务容器化运维:微博容器运维平台DCP
  18. 多属性决策模型 matlab代码及例子
  19. 利用Javascript动态生成表格的小demo
  20. 质量管理、质量保证、质量控制的区别

热门文章

  1. .NET下多线程初探
  2. Java开发笔记(一百三十五)Swing的文件对话框
  3. 【ANT】输入中文格式为乱码
  4. js手机号批量滚动抽奖代码实现
  5. [ACM训练] 算法初级 之 搜索算法 之 广度优先算法BFS (POJ 3278+1426+3126+3087+3414)
  6. 单机配置tomcat 8 集群
  7. 调试时遇到 调试源程序时Loaderlock 的解决办法
  8. 基于vue2.0+svg 拓扑组件
  9. 可以发送html文本的python脚本
  10. SharePoint 使用ECMAscript对象模型来读取帖子列表