bzoj1201: [HNOI2005]数三角形

Description

Input

大三角形的所有短边可以看成由(n+1)*n/2个单位三角形的边界组成。如下图的灰色三角形所示。其中第1排有1个灰色三角形,第2排有2个灰色三角形,……,第n排有n个灰色三角形。所以输入格式是这样规定的:输入第一行为正整数n,其中1<=n<=1000,表示大三角形每边的长度。接下来的n行,第i+1行有i组数,从左到右每组数描述一个三角形,每组数都有3个数,这3个数非0即1,表示对应的短边是否被删除,0表示已被删除,1表示未被删除,依次按照三角形的左、右、下边的顺序来描述。所以第i+1行有3i个数,每个数是0或1

 

Output

仅包含一个整数T,表示有多少个三角形的边界都没有被删除。

预处理每个点向右上、左下、右、左四个方向延伸的最大长度,枚举左上-右下方向的路径,计算一边在这条路径上的三角形个数,可以排序并用树状数组维护

#include<cstdio>
#include<algorithm>
char buf[1000000],*ptr=buf,*pmx=buf+1000000;
inline int g(){
    if(ptr==pmx)fread(ptr=buf,1,1000000,stdin);
    return *(ptr++);
}
int _(){
    int x=0,c=g();
    while(c<48)c=g();
    while(c>47)x=x*10+c-48,c=g();
    return x;
}
const int N=1107;
int n;
int d1[N][N],d2[N][N],d3[N][N],v1[N][N],v2[N][N],v3[N][N],v4[N][N],xs[N],xs2[N],bit[N],tk[N],T=0,ans=0;
struct itv{int l,r;}is[N],is2[N];
bool operator<(const itv&a,const itv&b){return a.l<b.l;}
void inc(int w){
    for(++w;w<N;w+=w&-w){
        if(tk[w]!=T)tk[w]=T,bit[w]=0;
        ++bit[w];
    }
}
int sum(int w){
    int s=0;
    for(++w;w;w-=w&-w){
        if(tk[w]!=T)tk[w]=T,bit[w]=0;
        s+=bit[w];
    }
    return s;
}
int main(){
    n=_();
    for(int i=1;i<=n;++i){
        for(int j=1;j<=i;++j){
            d1[i][j]=_();
            d3[i][j]=_();
            d2[i+1][j]=_();
        }
    }
    ++n;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=i;++j){
            if(d2[i][j-1])v2[i][j]=v2[i][j-1]+1;
            if(d1[i-1][j])v4[i][j]=v4[i-1][j]+1;
        }
        for(int j=i;j;--j)if(d2[i][j])v3[i][j]=v3[i][j+1]+1;
    }
    for(int i=n;i;--i){
        for(int j=1;j<=i;++j)if(d1[i][j])v1[i][j]=v1[i+1][j]+1;
    }
    for(int i=1;i<=n;++i){
        for(int x=i,y=1,p;y<=n;){
            while(!d3[x][y]&&y<=n)++x,++y;
            if(y>n)break;
            for(p=1;;++x,++y,++p){
                xs[p]=v1[x][y];
                is[p]=(itv){p-v2[x][y],p};
                xs2[p]=v3[x][y];
                is2[p]=(itv){p-v4[x][y],p};
                if(!d3[x][y])break;
            }
            std::sort(is+1,is+p+1);
            ++T;
            for(int w=1,r=1;w<=p;++w){
                while(r<=p&&is[r].l<=w)inc(is[r++].r);
                ans+=sum(w+xs[w])-sum(w);
            }
            std::sort(is2+1,is2+p+1);
            ++T;
            for(int w=1,r=1;w<=p;++w){
                while(r<=p&&is2[r].l<=w)inc(is2[r++].r);
                ans+=sum(w+xs2[w])-sum(w);
            }
        }
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/6073055.html