Codeforces edu 8 E. Zbazi in Zeydabad 树状数组 处理技巧
2016-02-23 10:57
387 查看
题目
题目链接:http://codeforces.com/contest/628/problem/E题目来源:Educational Codeforces Round 8
简要题意:给定一个含有’z’的矩阵,找到含有Z形的个数,全部是’z’,上下底和高相等。
题解
随便看了下这题,完全没有任何的想法啊。看了题解和其他人代码也是各种迷糊。
在图书馆思考了大概两个小时终于基本理解了其中一份代码。
解决起来需要使用到树状数组。
具体方法是按照反对角线去维护2n个树状数组,里头存合法的位置。
预处理出左边右边左下连续z的个数,这些都是Θ(n2)\Theta(n^2)的。
可以发现这样后z形整个的矩形的右上和左下角就足够判断是否能够构成了。
设右上角[x][y][x][y]左下角[i][j][i][j]假定下边都z判断min(l[x][y],ld[x][y])⩾y−j+1\min(l[x][y], ld[x][y])\geqslant y-j+1
于是j⩾y+1−min(l[x][y],ld[x][y])j \geqslant y+1-\min(l[x][y], ld[x][y]),又有j⩽yj\leqslant y
右上角左下角属于一条反对角线,而每个里面jj对应的是唯一的,于是按它维护。
加入时机时机就是j+r[i][j]−1j+r[i][j]-1这个位置去向i+ji+j的树状数组加上个jj
代码
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <queue> #include <string> #include <vector> #include <set> #include <map> #define fi first #define se second using namespace std; typedef long long LL; typedef pair<int,int> PII; // head const int N = 3000+5; struct BIT { int tree ; inline int lowbit(int x) { return x&(-x); } void add(int x, int n) { for (int i = x; i <= n; i += lowbit(i)) { tree[i]++; } } int sum(int x) { int ans = 0; for (int i = x; i > 0; i -= lowbit(i)) { ans += tree[i]; } return ans; } void clear(int n) { for (int i = 1; i <= n; i++) { tree[i] = 0; } } }; BIT bt[N<<1]; int n, m; char s ; int l , r , ld ; vector<PII> bk ; bool isValid(int x, int y) { return x > 0 && x <= n && y > 0 && y <= m; } void mov(int &x, int &y) { x--, y++; } void cal(LL &ans, int x, int y) { int v = min(l[x][y], ld[x][y]); int pos = x + y; if (!v) return; ans += bt[pos].sum(y) - bt[pos].sum(y - v); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%s", s[i]+1); for (int j = 1; j <= m; j++) { l[i][j] = s[i][j] == 'z' ? l[i][j-1] + 1 : 0; } } for (int i = n; i > 0; i--) { for (int j = m; j > 0; j--) { r[i][j] = s[i][j] == 'z' ? r[i][j+1] + 1 : 0; ld[i][j] = s[i][j] == 'z' ? ld[i+1][j-1] + 1 : 0; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int ub = j + r[i][j] - 1; bk[ub].push_back(make_pair(i, j)); } } LL ans = 0; for (int j = m; j > 0; j--) { for (int i = 0; i < bk[j].size(); i++) { int x = bk[j][i].fi, y = bk[j][i].se; bt[x + y].add(y, m); } for (int i = 1; i <= n; i++) { cal(ans, i, j); } } printf("%I64d\n", ans); return 0; }
相关文章推荐
- S3C2440 SDRAM内存驱动
- 点击子元素的时候阻止父元素也被点击
- web项目集成shiro后加入tomcat启动超时,tomcat无法正常启动
- 请求发送者与接收者解耦——命令模式
- Android.mk的用法和基础
- 原动力,与天赋的问题
- 文章标题
- Dell PowerEdge R710 内存基本插法
- Android UI效果之绘图篇(三)
- 自动构建 Unity Build 编译方式的 CMake 脚本
- 应用性能优化: 如何将应用延迟降低为 0 ms
- 玩转 Varnish 缓存代理
- Xcode模拟器正常显示图片,真机无法显示,找不到图片
- Dianping River Plugin for Elasticsearch
- GitHub for Windows提交失败“failed to sync this branch”
- nginx+tomcat集群配置(4)--rewrite规则和多应用根目录设定思路
- js获得桌面size
- Oracle 分区表的新增、修改、删除、合并。普通表转分区表方法
- Ubuntu 软件源sources.list
- Jenkins进阶系列之——02email-ext邮件通知模板