Educational Codeforces Round 8(E. Zbazi in Zeydabad(树状数组优化))★ ★

转载 2016年08月31日 16:38:57

题意:一个n*m矩阵, 里面的格子除了'z'就是'.',问有多少个z形图案。

思路:因为n和m很大, 即使n^3复杂度也会超时。  如果按照最朴素的方法, 我们可以处理一下前缀和, 处理出一个格子向左l[i][j]、向右r[i][j]、斜向左下lr[i][j]连着的z到哪里为止, 这样我们用n^2复杂度枚举每一个格子作为z形图案的右上角,取min(l[i][j], lr[i][j]), 就可以立刻知道这个z形的最左下角到哪里, 然后在这个对角线上扫一遍, 看看向右最远是不是符合条件,复杂度n^3。  我们注意到, 最后一步是处理一个对角线区间上的问题。  这其实可以用树状数组快速累加和。

我们只需要从右向左枚举每一列, 将以这一列为最右端的线段最左端加进树状数组, 那么我们再枚举这一列的所有点作为Z形的右上角, 算出左下角。  由于只有同一对角线上的行加列相同, 所以以此为树状数组编号, 开n + m棵树状数组, 就可以快速累加在这个对角线上的满足列介于上面那一横的范围内的下面那一横的数量了。 又以为从右向左枚举列, 所以先加的一定满足之后的。


#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 3100
#define MOD 1000000007

int T,n,m, bit[maxn*2][maxn],l[maxn][maxn];
int lr[maxn][maxn],r[maxn][maxn];
long long ans = 0;
struct node
{
    int x, y;
};
vector<node> g[maxn];
char s[maxn][maxn];

int sum(int i, int x)
{
    int ans = 0;
    while(x > 0)
    {
        ans += bit[i][x];
        x -= x & -x;
    }
    return ans;
}
void add(int i, int x, int d)
{
    while(x <= m)
    {
        bit[i][x] += d;
        x += x & -x;
    }
}
void pre()
{
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(s[i][j] == 'z')
                l[i][j] = l[i][j-1] + 1;
            else
                l[i][j] = 0;
        }
        for(int j = m; j >= 1; j--)
        {
            if(s[i][j] == 'z')
                r[i][j] = r[i][j+1] + 1;
            else
                r[i][j] = 0;
        }
    }
    for(int i = n; i >= 1; i--)
    {
        for(int j = 1; j <= m; j++)
        {
            if(s[i][j] != 'z')
            {
                lr[i][j] = 0;
                continue;
            }
            if(j-1 >= 1 && i+1 <= n)
                lr[i][j] = lr[i+1][j-1] + 1;
            else
                lr[i][j] = 1;
        }
    }
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            g[j + r[i][j] - 1].push_back(node{i,j});
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++)
        scanf("%s",s[i]+1);
    ans = 0;
    pre();
    for(int j = m; j >= 1; j--)
    {
        int len = g[j].size();
        for(int i = 0; i < len; i++)
        {
            int x = g[j][i].x, y = g[j][i].y;
            add(x+y, y, 1);
        }
        for(int i = 1; i <= n; i++)
        {
            if(s[i][j] != 'z')
                continue;
            int len = min(l[i][j], lr[i][j]);
            ans += sum(j+i, j) - sum(i+j, j-len);
        }
    }
    printf("%I64d\n",ans);
    return 0;
}


相关文章推荐

Educational Codeforces Round 8(E. Zbazi in Zeydabad(树状数组优化))

题目链接:点击打开链接 题意:一个n*m矩阵, 里面的格子除了'z'就是'.',问有多少个z形图案。 思路:因为n和m很大, 即使n^3复杂度也会超时。  如果按照最朴素的方法, 我们可以处理一下...

Codeforces edu 8 E. Zbazi in Zeydabad 树状数组 处理技巧

利用数据结构进行技巧性处理的好题。

Educational Codeforces Round 8 E. Zbazi in Zeydabad(给你一个n*m矩阵,每个点可能是'.'或者'z',问有多少种Z子型(Z为一个正方形))

传送门:Educational Codeforces Round 8 E. Zbazi in Zeydabad 题意:给你一个n*m矩阵,每个点可能是’.’或者’z’,问有多少种Z子型(Z为一个正...

Educational Codeforces Round 8 E - Zbazi in Zeydabad

http://codeforces.com/contest/628/problem/E L[i][j]  表示(i,j)左边连续的‘z’个数 R[i][j] 表示右边 D[i][j] 从...

Educational Codeforces Round 10D 离散化+树状数组

点击打开链接 题意: 有n条线段, n 分析: 求每条线段覆盖的其他线段的数量, 就是求其他线段左端点 l'>=l 并且右端点 r'...

【Educational Codeforces Round 10D】【树状数组】Nested Segments 每条线段内部有多少条线段

D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes ...

【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望

E. Kleofáš and the n-thlon time limit per test 1 second memory limit per test 256 megaby...

Codeforces Round #401 (Div. 2) E 离散化 + 树状数组/线段树

题目链接思路: 感觉像是背包问题的变形….. 很直接的DP策略: 首先先对物体进行排序,外半径大的先处理。(考虑无后效性,因为对于外半径最大的物品是不能堆在其他物品上面的。) 设dp[i]是处...

Codeforces Round #301 (Div. 2)E(树状数组+离散化)

E. Infinite Inversions time limit per test 2 seconds memory limit per test 256 megabytes input...

Codeforces Round #424 (Div. 2) E. Cards Sorting(思维 树状数组)

题意:有n张牌,每张牌上有一个数,每次从牌顶取一张牌,如果这张牌是剩余牌中的最小值那么就把它扔掉,不然放到牌堆底,问多少次操作才能把 牌扔光。 思路:树状数组维护每个位置的牌是否存在,这样就能lo...
  • CillyB
  • CillyB
  • 2017年07月15日 15:15
  • 141
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Educational Codeforces Round 8(E. Zbazi in Zeydabad(树状数组优化))★ ★
举报原因:
原因补充:

(最多只允许输入30个字)