【Foreign】画方框 [主席树]
画方框
Time Limit: 10 Sec Memory Limit: 256 MB
Description
Input
Output
输出一行一个整数,表示 CD 最多可能画了几个方框。
Sample Input
3
1 1 1
1 0 1
1 1 1
Sample Output
9
HINT
Main idea
给定一个01矩阵,1表示有标记,询问正方形方框的个数。
Solution
首先,我们先从 维护对角线上的点 这一层面来考虑。
我们先把一个点 能向左向上拓展的最大长度 以及 能向右向下的最长长度 预处理出来。
那么这时候,我们考虑 对于一条对角线上的点 怎么 在O(nlogn)以内 统计出答案。必然要用到某些数据结构。
举个例子,比如这个数据:
1 1 1 1
1 0 0 0
1 0 0 1
1 0 1 1
我们现在统计中间对角线的答案。
现在查询第一个点(1,1),他向右向下拓展长度为 4 。
就是查询,后面三个点中 可以向左上拓展的长度 (2,2)>=1 (3,3)>=2 (4,4)>=3,
这三个条件满足了几个。
这样的话,我们发现:每次统计一个点的时候 查询的就是:在这个点 可以向右向下拓展 到的范围内,它后面的第 i 个点 可以向左向上拓展长度 是否 > i。
我们发现:查询后面若干个数的值是否 > 一个等差数列比较复杂。
于是乎,若统计第id个的答案,后面第num个点(在向右向下范围内)可以被统计所需要满足的条件是:num - id + 1 <= val 也就是 num - val + 1 <= id。(其中val表示 这个点可以向左向上拓展的长度)
所以我们如果把 i - val + 1 加入到一个数据结构中的话,
查询的就是:某一范围内 <=一个定值 的数的个数。
那直接用主席树来做就好了。
这样我们就解决了这个问题 QWQ。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long s64; const int ONE = ;
const int INF = ; int n;
int a[ONE][ONE];
int Ans; struct power
{
int left, right;
int up, down;
int L, R;
}A[ONE][ONE]; int cnt, res;
struct point
{
int root;
int value;
int left, right;
}Node[ONE * ]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Deal_first()
{
for(int i = ; i <= n; i++)
{
for(int j = n; j >= ; j--)
if(a[i][j]) A[i][j].right = A[i][j + ].right + ;
else A[i][j].right = ;
for(int j = ; j <= n; j++)
if(a[i][j]) A[i][j].left = A[i][j - ].left + ;
else A[i][j].left = ;
} for(int j = ; j <= n; j++)
{
for(int i = n; i >= ; i--)
if(a[i][j]) A[i][j].down = A[i + ][j].down + ;
else A[i][j].down = ;
for(int i = ; i <= n; i++)
if(a[i][j]) A[i][j].up = A[i - ][j].up + ;
else A[i][j].up = ;
} for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
A[i][j].L = min(A[i][j].left, A[i][j].up),
A[i][j].R = min(A[i][j].right, A[i][j].down);
} void Update(int &x, int y, int L, int R, int Q, int val)
{
x = ++cnt;
Node[x].left = Node[y].left;
Node[x].right = Node[y].right;
Node[x].value = Node[y].value + val;
if(L == R) return; int M = L + R >> ;
if(Q <= M)
Update(Node[x].left, Node[y].left, L, M, Q, val);
else
Update(Node[x].right, Node[y].right, M + , R, Q, val);
} void Query(int x, int y, int l, int r, int L, int R)
{
if(L <= l && r <= R)
{
res += Node[y].value - Node[x].value;
return;
} int mid = l + r >> ; if(L <= mid) Query(Node[x].left, Node[y].left, l, mid, L, R);
if(mid + <=R) Query(Node[x].right, Node[y].right, mid + , r, L, R);
} int main()
{
n = get();
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
a[i][j] = get(); Deal_first(); for(int id = ; id <= n; id++)
{
for(int x = id, y = ; x <= n; x++, y++)
Update(Node[y].root, Node[y - ].root, , INF, y - A[x][y].L + , ); for(int x = id, y = ; x <= n; x++, y++)
{
res = ;
if(A[x][y].R)
Query(Node[y - ].root, Node[y + A[x][y].R - ].root, , INF, , y);
Ans += res;
} cnt = ;
for(int i = ; i <= cnt; i++)
Node[i].left = Node[i].right = Node[i].root = Node[i].value = ;
} for(int id = ; id <= n; id++)
{
for(int y = id, x = ; y <= n; y++, x++)
Update(Node[x].root, Node[x - ].root, , INF, x - A[x][y].L + , ); for(int y = id, x = ; y <= n; y++, x++)
{
res = ;
if(A[x][y].R)
Query(Node[x - ].root, Node[x + A[x][y].R - ].root, , INF, , x);
Ans += res;
} cnt = ;
for(int i = ; i <= cnt; i++)
Node[i].left = Node[i].right = Node[i].root = Node[i].value = ;
} printf("%d", Ans);
}
【Foreign】画方框 [主席树]的更多相关文章
- 主席树入门(区间第k大)
主席树入门 时隔5个月,我又来填主席树的坑了,现在才发现学算法真的要懂了之后,再自己调试,慢慢写出来,如果不懂,就只会按照代码敲,是不会有任何提升的,都不如不照着敲. 所以搞算法一定要弄清原理,和代码 ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- BZOJ 4539: [Hnoi2016]树 [主席树 lca]
4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...
- bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- 五月月赛 寻宝 exkmp + 主席树
: 寻宝 时间限制: Sec 内存限制: MB 提交: 解决: [提交] [状态] [讨论版] [命题人:admin] 题目描述 采蘑菇的小西佬找到了一张上古年间的藏宝图,上面画着m座连绵不断的山,他 ...
- 【学术篇】CF833B TheBakery 分治dp+主席树
题目の传送门~ 题目大意: 将\(n\)个蛋糕分成恰好\(k\)份, 求每份中包含的蛋糕的种类数之和的最大值. 这题有两种做法. 第一种是线段树优化dp, 我还没有考虑. 另一种就是分治+主席树. 然 ...
- 权值线段树&&可持久化线段树&&主席树
权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...
- bzoj3207--Hash+主席树
题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...
随机推荐
- pthon_flask小汇总
一.Jinja2中的关键字 1.include关键字 用include可以导入另外一个模板到当前模板中 <pre> {% include 'header.html' %} Body {% ...
- Beta完结--感想及吐槽
Beta冲刺结束啦!!! Beta冲刺结束啦!!! Beta冲刺结束啦!!! 这时候每个人的心情肯定都是非常激动的.随着Beta冲刺的结束,折磨了我们一整个学期的软工实践也差不多结束了.(实在是太不容 ...
- PART1 一些想法
其实我一直是一个后知后觉的人,这点也是我过了好久才发现的问题,之所以晚发现自己这个毛病,是因为后知后觉==,这有点像是个悖论或者是笑话,但的确是真实存在于我的身上.其实当初为啥来这个学校选计算机的专业 ...
- Python 零碎信息-基础 02
1. range xrange 的差别 1.1 range 返回列表对象. 1.2 xrange 返回xrange对象 不需要返回列表里面的值, 节省内存. >>> range(1 ...
- 3dContactPointAnnotationTool开发日志(六)
一种可行的思路就是枚举一个模型的三角面片,然后判断三角形是否与另一个物体相交即可.为了让效果更好我想只渲染模型的线框. 在网上查了半天好像Unity里都没有自带的方便的渲染线框的方式,我又自己 ...
- python爬虫 --- 简书评论
某些网站的一些数据是通过js加载的 ,所以爬取下来的数据拿不到, 找到评论的地址 .进行请求获取评论数据 #coding=utf-8 import json import requests def r ...
- 【Linux】- CentOS搭建FTP服务器
1.安装vsftpd yum install -y vsftpd 2.启动vsftpd服务 service vsftpd start 3.查看运行状态 netstat -nltp | 完毕!!! 参考 ...
- Ubuntu编译内核树
什么是内核树?刚开始我也没弄明白,通过这几天的学习,有所感悟,就说说我的理解吧!从形式上看,内核树与内核源码的目录结构形式是相同的,都是由各个层次的文件目录结构组成,但是其中的具体内容肯定是不同的.从 ...
- [计算机网络] 互联网协议栈(TCP/IP参考模型)各层的主要功能及相应协议
应用层:提供用户与网络间的接口.----HTTP.FTP.SMTP 运输层:进程到进程间的数据传输.---TCP.UDP 网络层:主机到主机之间的数据传输.---IP.选路协议 数据链路层:相邻结点之 ...
- mysql(三) 慢查询分析(二)
在一般的查询中,都要求尽量围绕创建的索引进行.针对索引,常用的有主键索引,单列索引,组合索引,索引合并等. 在评价索引时,关键看区分度.索引区分度=索引列唯一值/表记录数. 如果在区分度很低的列上建索 ...