洛谷 P2315 [HNOI2005]数三角形 暴力

版权声明:2333 https://blog.csdn.net/liangzihao1/article/details/82631209

题目描述
这里写图片描述
输入输出格式

输入格式:
这里写图片描述

输出格式:
输出文件output.txt中仅包含一个整数T,表示有多少个三角形的边界都没有被删除。

输入输出样例

输入样例#1:
5
1 1 1
1 1 0 1 1 0
1 1 1 1 1 1 1 0 1
1 0 1 1 1 1 0 1 1 1 1 1
0 1 1 1 1 1 0 1 1 1 1 1 0 1 1
输出样例#1:
19

分析:
我们维护每个点往左上( l u ),左下( l d ),右上( r u ),右下( r d ),往左( l )最多能走多少步。
然后我们枚举每个点为正立的三角形的右下角,显然这个三角形最大边长是 m i n ( l u [ i ] [ j ] , l [ i ] [ j ] )
我们枚举这个长度 k ,显然另一个顶点为 ( i , j k ) ,然后判断 r u [ i ] [ j k ] 是否大于 k
这样做是 O ( n 3 ) 的,但是由于数据水,是能过的。
至于考虑优化,也就是要满足,

r u [ i ] [ j k ] >= k

也就是要查询一个区间 [ j m a x k ] [ j 1 ] 的大于 k 的数的个数,这个可以用可持久化权值线段树做。
复杂度是 O ( n 2 l o g n ) 的,但是不想打。

代码:

#include <iostream>
#include <cmath>
#include <cstdio>

const int maxn=1007;

using namespace std;

int n,x,y,z,ans;
int lu[maxn][maxn],ru[maxn][maxn],ld[maxn][maxn],rd[maxn][maxn];

struct rec{
    int l,r,d;
}h[maxn][maxn];

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=i;j++)
        {
            scanf("%d%d%d",&h[i][j].l,&h[i][j].r,&h[i][j].d);
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=i;j++)
        {
            if (h[i][j].l) ru[i+1][j]=ru[i][j]+1;
            if (h[i][j].r) lu[i+1][j+1]=lu[i][j]+1;
        }
    }
    for (int i=n;i>0;i--)
    {
        for (int j=i;j>0;j--)
        {
            if (h[i][j].l) ld[i][j]=ld[i+1][j]+1;
            if (h[i][j].r) rd[i][j]=rd[i+1][j+1]+1;
        }
    }       
    for (int i=1;i<=n+1;i++)
    {
        for (int j=1;j<=i;j++)
        {
            for (int k=j-1;(k>0) && (h[i-1][k].d) && (j-k<=lu[i][j]);k--)
            {
                ans+=(j-k)<=ru[i][k];
            }
            for (int k=j-1;(k>0) && (h[i-1][k].d) && (j-k<=ld[i][j]);k--)
            {
                ans+=(j-k)<=rd[i][k];
            }
        }
    }
    printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/liangzihao1/article/details/82631209
今日推荐