1201: [HNOI2005]数三角形 - BZOJ
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.