CodeForces 628E  Zbazi in Zeydabad

这个树状数组很巧妙。

将$O(n^3)$降到$O(n^2logn)$。

每个对角线的加和相等,建在一棵树上。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3005;
int c[maxn << 1][maxn];
int l[maxn][maxn];
int dig[maxn][maxn];
int r[maxn][maxn];
char s[maxn][maxn];
int n, m;
typedef long long ll;
void add(int id, int x)
{
    while(x <= n)
    {
        c[id][x] += 1;
        x += (x & -x);
    }
}
int sum(int id, int x)
{
    int res = 0;
    while(x > 0)
    {
        res += c[id][x];
         x -= (x & -x);
    }
    return res;
}
int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", s[i] + 1);
    }
    /// O(nm)预处理出向左的最长,向左下的最长,还有是不是水平线段的最右点
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(s[i][j] == '.')
            {
                l[i][j] = 0;
            }
            else if(s[i][j] == 'z')
            {
                l[i][j] = l[i][j - 1] + 1;
            }
            if(s[i][j + 1] != 'z')
            {
                r[i][j] = 0;
            }
            else r[i][j] = 1;
        }
    }
    for(int i = n; i >= 1; i--)
    {
        for(int j = 1; j <= m; j++)
        {
            if(s[i][j] == '.')
            {
                dig[i][j] = 0;
            }
            else
            {
                dig[i][j] = dig[i + 1][j - 1] + 1;
            }
        }
    }
    ll ans = 0;
    for(int j = m; j >= 1; j--)
    {
        for(int i = 1; i <= n; i++)
        {
            if(s[i][j] == 'z' && r[i][j] == 0)
            {
                int pos = j;
                while(s[i][pos] == 'z')
                {
                    add(i + pos, i);
                    pos--;
                }
            }
        }
        for(int i = 1; i <= n; i++)
        {
            if(s[i][j] == 'z') ///枚举右上端点
            {
                ans += sum(i + j, i + min(l[i][j], dig[i][j]) - 1) - sum(i + j, i - 1);
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}
Code

相关文章:

  • 2021-07-24
  • 2021-11-10
  • 2022-01-10
  • 2021-11-29
  • 2021-04-13
  • 2021-04-18
  • 2021-07-13
  • 2021-12-01
猜你喜欢
  • 2021-04-21
  • 2021-08-15
  • 2021-07-21
  • 2021-08-18
  • 2021-06-09
  • 2021-05-09
  • 2021-09-16
相关资源
相似解决方案