博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj1176】[Balkan2007]Mokia/【bzoj2683】简单题 CDQ分治+树状数组
阅读量:4455 次
发布时间:2019-06-07

本文共 2268 字,大约阅读时间需要 7 分钟。

bzoj1176

题目描述

维护一个W*W的矩阵,初始值均为S(题目描述有误,这里的S没有任何作用!).每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

输入

第一行两个整数,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:表示输入结束

输出

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

样例输入

0 4

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

样例输出

3

5


bzoj2683

题目描述

同上,只是少了一个烦人的S


题解

CDQ分治

先读入所有修改和询问操作,将每个修改拆成4个。

然后按照CDQ分治的套路,按x排序,按id比较,按y查询。

(好像这道题我写的和别的CDQ分治题不一样。。。)

代码是1176的,2683直接去掉%*d即可。

(就算S真的有用,可以直接改ans的初始值,也是一样的)

#include 
#include
using namespace std;struct data{ int x , y , v , p , id , opt;}a[800000] , tmp[800000];int n , tot , cnt , f[2000010] , ans[200000];bool cmp(data a , data b){ return a.x == b.x ? (a.y == b.y ? a.opt < b.opt : a.y < b.y) : a.x < b.x;}void add(int b , int c , int d , int t){ a[++tot].x = b , a[tot].y = c , a[tot].v = d , a[tot].id = tot , a[tot].opt = t; if(t) a[tot].p = cnt;}void update(int x , int a){ int i; for(i = x ; i <= n ; i += i & -i) f[i] += a;}int query(int x){ int i , ans = 0; for(i = x ; i ; i -= i & -i) ans += f[i]; return ans;}void solve(int l , int r){ if(l == r) return; int mid = (l + r) >> 1 , i , p1 = l , p2 = mid + 1; for(i = l ; i <= r ; i ++ ) { if(a[i].id <= mid && !a[i].opt) update(a[i].y , a[i].v); if(a[i].id > mid && a[i].opt) ans[a[i].p] += a[i].v * query(a[i].y); } for(i = l ; i <= r ; i ++ ) if(a[i].id <= mid && !a[i].opt) update(a[i].y , -a[i].v); for(i = l ; i <= r ; i ++ ) { if(a[i].id <= mid) tmp[p1 ++ ] = a[i]; else tmp[p2 ++ ] = a[i]; } for(i = l ; i <= r ; i ++ ) a[i] = tmp[i]; solve(l , mid) , solve(mid + 1 , r);}int main(){ int i , k , b , c , d , e; scanf("%*d%d" , &n); while(scanf("%d" , &k) && k != 3) { if(k == 1) scanf("%d%d%d" , &b , &c , &d) , add(b , c , d , 0); else scanf("%d%d%d%d" , &b , &c , &d , &e) , cnt ++ , add(d , e , 1 , 1) , add(b - 1 , e , -1 , 1) , add(d , c - 1 , -1 , 1) , add(b - 1 , c - 1 , 1 , 1); } sort(a + 1 , a + tot + 1 , cmp); solve(1 , tot); for(i = 1 ; i <= cnt ; i ++ ) printf("%d\n" , ans[i]); return 0;}

 

 

 

转载于:https://www.cnblogs.com/GXZlegend/p/6617205.html

你可能感兴趣的文章
Jquery:怎样让子窗体的div显示在父窗体之上
查看>>
01概率
查看>>
.NET LINQ 元素操作
查看>>
Shell脚本
查看>>
MatLab Load cv::Mat 导入数据
查看>>
html+css相关笔记(一)
查看>>
基于块流协议保证音频优先发送
查看>>
关于互联网的一些数据
查看>>
nginx+lua_nginx+GraphicsMagick生成实时缩略图
查看>>
数据预处理:独热编码(One-Hot Encoding)
查看>>
python将对象名的字符串类型,转化为相应对象的操作方法
查看>>
如何删除Dead状态的container
查看>>
【NLP新闻-2013.06.03】New Book Where Humans Meet Machines
查看>>
mongodb安装4.0(rpm)
查看>>
DispatcherServlet的url mapping为“/”时,对根路径访问的处理
查看>>
备忘pwnable.kr 之passcode
查看>>
好久没敲代码了,手有点生——一个小小的时钟
查看>>
运算符 AS和IS 的区别
查看>>
(转)详解C中volatile关键字
查看>>
easyui时的时间格式yyyy-MM-dd与yyyy-MM-ddd HH:mm:ss
查看>>