bzoj1176【Balkan2007】Mokia
1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MB
Submit: 1683 Solved: 732
[ Submit][ Status][ Discuss]
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
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
5
HINT
保证答案不会超过int范围
CDQ分治+树状数组
对于一个矩形的询问,根据容斥原理可以拆成四个询问,然后将询问和修改一起CDQ分治。
每一层处理[l,mid]对[mid+1,r]答案的影响,先保证x有序,然后树状数组维护就可以了。
最开始的sort保证了每一层处理时x都有序。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 200005
using namespace std;
int s,w,n,cnt;
int ans[10005],sum[2000005];
struct data{int x,y,z,pos,id;}a[maxn],b[maxn];
inline int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
inline bool cmp(data a,data b)
{if (a.x==b.x&&a.y==b.y) return a.pos<b.pos;else if (a.x==b.x) return a.y<b.y;else return a.x<b.x;
}
inline void add(int x,int v)
{for(int i=x;i<=w;i+=i&(-i)) sum[i]+=v;
}
inline int query(int x)
{int ret=0;for(int i=x;i;i-=i&(-i)) ret+=sum[i];return ret;
}
inline void solve(int l,int r)
{if (l==r) return;int mid=(l+r)>>1,l1=l,l2=mid+1;
// memset(sum,0,sizeof(sum));//这样写会TLE F(i,l,r){if (a[i].id<=mid&&!a[i].pos) add(a[i].y,a[i].z);if (a[i].id>mid&&a[i].pos) ans[a[i].pos]+=query(a[i].y)*a[i].z;}F(i,l,r) if (a[i].id<=mid&&!a[i].pos) add(a[i].y,-a[i].z);//如果把这句话替换成memset会TLE F(i,l,r){if (a[i].id<=mid) b[l1++]=a[i];else b[l2++]=a[i];}F(i,l,r) a[i]=b[i];solve(l,mid);solve(mid+1,r);
}
int main()
{s=read();w=read();for(;;){int opt=read();if (opt==1){int x=read(),y=read(),z=read();n++;a[n]=(data){x,y,z,0,n};}else if (opt==2){int x1=read()-1,y1=read()-1,x2=read(),y2=read();ans[++cnt]=(x2-x1)*(y2-y1)*s;n++;a[n]=(data){x1,y1,1,cnt,n};n++;a[n]=(data){x1,y2,-1,cnt,n};n++;a[n]=(data){x2,y1,-1,cnt,n};n++;a[n]=(data){x2,y2,1,cnt,n};}else break;}sort(a+1,a+n+1,cmp);solve(1,n);F(i,1,cnt) printf("%d\n",ans[i]);return 0;
}
还有一种写法是最开始不sort,即最初状态是按照时间从小到大。
每次分治的时候先分治处理两个子区间,然后按照横坐标归并排序,最后计算答案。
两个算法复杂度都是O(n*logn)。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 200005
using namespace std;
int s,w,n,cnt;
int ans[10005],sum[2000005];
struct data{int x,y,z,pos,id;}a[maxn],b[maxn];
inline int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
inline bool cmp(data a,data b)
{return a.x!=b.x?a.x<b.x:a.id<b.id;
}
inline void add(int x,int v)
{for(int i=x;i<=w;i+=i&(-i)) sum[i]+=v;
}
inline int query(int x)
{int ret=0;for(int i=x;i;i-=i&(-i)) ret+=sum[i];return ret;
}
inline void solve(int l,int r)
{if (l==r) return;int mid=(l+r)>>1,l1=l,l2=mid+1,tmp=l;solve(l,mid);solve(mid+1,r);while (l1<=mid&&l2<=r) b[tmp++]=cmp(a[l1],a[l2])?a[l1++]:a[l2++];while (l1<=mid) b[tmp++]=a[l1++];while (l2<=r) b[tmp++]=a[l2++];F(i,l,r) a[i]=b[i];F(i,l,r){if (a[i].id<=mid&&!a[i].pos) add(a[i].y,a[i].z);if (a[i].id>mid&&a[i].pos) ans[a[i].pos]+=a[i].z*query(a[i].y);}F(i,l,r) if (a[i].id<=mid&&!a[i].pos) add(a[i].y,-a[i].z);
}
int main()
{s=read();w=read();for(;;){int opt=read();if (opt==1){int x=read(),y=read(),z=read();n++;a[n]=(data){x,y,z,0,n};}else if (opt==2){int x1=read()-1,y1=read()-1,x2=read(),y2=read();ans[++cnt]=(x2-x1)*(y2-y1)*s;n++;a[n]=(data){x1,y1,1,cnt,n};n++;a[n]=(data){x1,y2,-1,cnt,n};n++;a[n]=(data){x2,y1,-1,cnt,n};n++;a[n]=(data){x2,y2,1,cnt,n};}else break;}solve(1,n);F(i,1,cnt) printf("%d\n",ans[i]);return 0;
}
bzoj1176【Balkan2007】Mokia相关推荐
- 【BOI2007】Mokia 摩基亚
传送门 CDQ分治板子题 其实和陌上花开差不多 把时间. l . r l.r l.r看成三个维度 像二维树状数组统计一样,把每一个询问拆成四块前缀和相减 然后统计答案的时候容斥一下 那么现在需要考虑的 ...
- 【教程】简易CDQ分治教程学习笔记
前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦! CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...
- 【CentOS】利用Kubeadm部署Kubernetes (K8s)
[CentOS]利用Kubeadm部署Kubernetes (K8s)[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体实验流程 1 系统准 ...
- 【Spring】框架简介
[Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...
- 【C#】类——里式转换
类是由面对对象程序设计中产生的,在面向结构的程序设计例如C语言中是没有类这个概念的!C语言中有传值调用和传址调用的两种方式!在c语言中,主方法调用方法,通过传递参数等完成一些操作,其中比较常用的的数据 ...
- 【C#】Out与ref是干什么的?
关于return: 1.最后没有写 return 语句的话,表示程序正常退出 2.不需要返回值时,存在return的作用 例子 void main() {return; //return退出该程序的作 ...
- 【软件工程】RUP与软件开发5大模型
软件开发的5大模型 1.瀑布模型:按照人的思维一步一步的开发下去,如果需求分析得当,每个阶段顺利,结果还不错! 2.快速原型模型:后来人们发现,自己不可能一下子就把所有的需求搞清楚,总是在开发的过程中 ...
- 【VB】学生信息管理系统5——数据库代码
这次学生信息管理系统在代码的理解过程中遇到了一些问题.总结如下: 1. sql server的安装过程各个步骤的意思.在安装SQL Server的时候按照网上的步骤,我觉得这个需要学完整个数据库再返回 ...
- 白化(预处理步骤)【转】
白化(预处理步骤)[转] 介绍 我们已经了解了如何使用PCA降低数据维度.在一些算法中还需要一个与之相关的预处理步骤,这个预处理过程称为白化.举例来说,假设训练数据是图像,由于图像中相邻像素之间具有很 ...
最新文章
- 【机器学习】机器学习12个关键经验教训
- 【PC工具】几个电脑录屏相关软件,手机投屏电脑,电脑显示手机摄像头图像,必须好用无广告!...
- 24-hadoop-hiveserver2jdbc-正则数据导入
- 80后,天才程序员, Facebook 第一任 CTO,看看开挂的人生到底有多变态?
- C语言学习之求1+2+3+···+100的值
- Kafka官方文档翻译——实现
- ASP与ActiveX控件交互实战(一)
- 修改linq结果集_linq 查询的结果会开辟新的内存吗?
- Can not find the tag library descriptor for http://java.sun.com/jsp/jst1/core
- ZZULIOJ 1882: 蛤玮的魔法【数学】
- Could not connect to appstore: cURL error 28: Operation timed out after 60000 milliseconds with
- CodeCademy | Python | 6. Pyglatin
- 将1自动补位为01_自动补位为辅助后游戏就输了一半?那是你不懂辅助的正确打开方式...
- 【uni-app】解决iPhone X “刘海屏”兼容性问题
- 如何防止自己的电脑成为肉鸡?
- Beginning Auto Layout Tutorial in iOS 7: Part 2
- python实现去重_Python列表去重的4种实现方法
- 【曹工杂谈】Maven底层容器Plexus Container的前世今生,一代芳华终落幕
- ARCGIS10.2加载天地图不显示
- Arduino安装esp32 SDK(Windows)问题:AzureIoT: no headers files解决