• 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
  • 相关阅读:
    C++解决单纯形表
    VS2010 MFC Excel(3)
    VS2010 MFC Excel(1)
    VS2010 MFC 读取Excel(2)
    读取数量不定的输入数据
    牛顿插值
    连接数据库
    雅克比迭代
    NOIP模拟 24
    NOIP模拟 23
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3610552.html
Copyright © 2020-2023  润新知