版权声明: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
分析:
我们维护每个点往左上(
),左下(
),右上(
),右下(
),往左(
)最多能走多少步。
然后我们枚举每个点为正立的三角形的右下角,显然这个三角形最大边长是
。
我们枚举这个长度
,显然另一个顶点为
,然后判断
是否大于
。
这样做是
的,但是由于数据水,是能过的。
至于考虑优化,也就是要满足,
也就是要查询一个区间 的大于 的数的个数,这个可以用可持久化权值线段树做。
复杂度是 的,但是不想打。
代码:
#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);
}