1201: [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,表示有多少个三角形的边界都没有被删除。
Sample Input
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
Sample Output
19

统计有多少个三角形

枚举底边所在的直线

对于一个三角形,它的条件是底边是实线,左右两边要比底边长

我们先预处理出exl和exr,分别表示往左上最多延伸多长,往右上最多延伸多长

对于底边两点i和j,i<j

它需要满足的条件是(实线我们可以直接一段一段的处理)

j-i<=exr[i],j-i<=exl[j]

所以j<=exr[i]+i,j-exl[j]<=i

然后我们先把j-exl[j]排一个序,从小到大枚举i,加入j-exl[j]<=i的点(即a[j]++),注意要把j<=i的减掉

a[i]数组用树状数组维护,再统计a数组中[1..exr[i]+i]的和就可以了

一开始不知道,所以我把每一个j看成一个平面上的点,坐标为(j,j-exl[j]),枚举i,统计横坐标小于等于exr[i]+i且纵坐标小于等于i的点

用二维树状数组维护这个和,然后过了

这里就只贴二维的那个了(第一种方法没有写)

  1 const
  2     maxn=1010;
  3 var
  4     tri:array[0..maxn,0..maxn,1..3]of integer;
  5     exl,exr,c:array[0..maxn,0..maxn]of integer;
  6     n,ans:longint;
  7  
  8 function max(x,y:longint):longint;
  9 begin
 10         if x>y then exit(x);
 11         exit(y);
 12 end;
 13  
 14 function min(x,y:longint):longint;
 15 begin
 16         if x<y then exit(x);
 17         exit(y);
 18 end;
 19  
 20 procedure init;
 21 var
 22     i,j:integer;
 23 begin
 24     read(n);
 25     for i:=1 to n do
 26       for j:=1 to i do
 27         read(tri[i,j,1],tri[i,j,2],tri[i,j,3]);
 28 end;
 29  
 30 function lowbit(x:longint):longint;
 31 begin
 32     exit(x and -x);
 33 end;
 34  
 35 procedure add(x,y,z:longint);
 36 var
 37     h:longint;
 38 begin
 39     while x<=n+1 do
 40       begin
 41         h:=y;
 42         while h<=n+1 do
 43           begin
 44             inc(c[x,h],z);
 45             h:=h+lowbit(h);
 46           end;
 47         x:=x+lowbit(x);
 48       end;
 49 end;
 50  
 51 function sum(x,y:longint):longint;
 52 var
 53     h:longint;
 54 begin
 55     sum:=0;
 56     while x>0 do
 57       begin
 58         h:=y;
 59         while h>0 do
 60           begin
 61             inc(sum,c[x,h]);
 62             h:=h-lowbit(h);
 63           end;
 64         x:=x-lowbit(x);
 65       end;
 66 end;
 67  
 68 procedure get;
 69 var
 70     h,l,r,i:longint;
 71 begin
 72     for h:=1 to n do
 73       begin
 74         l:=1;
 75         while l<=h do
 76           begin
 77             while (tri[h,l,3]=0)and(l<=h) do
 78               inc(l);
 79             if l>h then break;
 80             r:=l+1;
 81             while tri[h,r,3]=1 do
 82               inc(r);
 83             for i:=l to r do
 84               add(i,max(1,i-exl[h,i]),1);
 85             for i:=l to r do
 86               begin
 87                 add(i,max(1,i-exl[h,i]),-1);
 88                 inc(ans,sum(min(n+1,exr[h,i]+i),i));
 89               end;
 90             l:=r+1;
 91           end;
 92       end;
 93 end;
 94  
 95 procedure work;
 96 var
 97     i,j:longint;
 98 begin
 99     for i:=1 to n do
100       for j:=1 to i do
101         begin
102           if tri[i,j,1]=1 then exr[i,j]:=exr[i-1,j]+1;
103           if tri[i,j,2]=1 then exl[i,j+1]:=exl[i-1,j]+1;
104         end;
105     get;
106     for i:=1 to n do
107       for j:=1 to i+1 do
108         begin
109           exl[i,j]:=0;
110           exr[i,j]:=0;
111         end;
112     for i:=n downto 1 do
113       for j:=1 to i do
114         begin
115           if tri[i,j,1]=1 then exl[i-1,j]:=exl[i,j]+1;
116           if tri[i,j,2]=1 then exr[i-1,j]:=exr[i,j+1]+1;
117         end;
118     get;
119     write(ans);
120 end;
121  
122 begin
123     init;
124     work;
125 end.
View Code
原文地址:https://www.cnblogs.com/Randolph87/p/3610552.html