usaco 6.1

  6.1.2 rectbarn

  首先要注意空间的消耗,3000*3000 大概10m的样子(最多16m),只够开个char,本想套用big barn的dp方法,定义struct [i,j]{int l;int h}来表示以(i,j)为右上顶点的矩形,貌似这样会爆,只好考虑其它解法(参考wc2003王知昆的论文).

  大概思路:

  定义h[i,j],l[i,j],r[i,j]分别表示以点p(i,j)为下端的最大拓展高度,p左侧离p最近的一个障碍点(初始化为-1),p右侧离p最近的障碍点(初始化为c+1),则p确定了一个无法再继续拓展的极大矩形,这样只要对每个点求它确定的矩形就能得到结果,这是一个O(R*C)的算法.

  具体实现:

  h[i,j]=h[i-1,j]+1  (i,j)不为障碍点

  否则h[i,j]=0, 可以用滚动数组优化.

  需要特别注意的是l,和r的使用.拿l来说,线段(i,i+h[i,j])并不一定能移动到l[i,j],因为如果上面存在障碍点,就可能把它包括到矩形里去,这是非法的,为了解决这个问题,要修改l的定义.即l[i,j]为(i,j)向左拓展到最远的点,那么l[i,j]必定要>=l[i-1,j],即l[i,j]要在l[i-1,j]的右侧,所以得到新的求l的方程:

    定义tl[i,j]为(i,j)左侧最近的障碍点(初始化为-1可以通过dp得到),l[i,j]=max(l[i-1,j],tl[i,j]);

  实现的时候犯了个错误,在此记录一下:

    如果p(i,j)为障碍点,l[i,j]通过定义式会得到l[i,j]=j;dp到下一行时,在(i+1,j)点就会出错,所以应该特殊判断一下若(i-1,j)为障碍点则 l[i,j] 为tl[i,j].

 

 6.1.3 cowxor

 通过这题学到了一个求一段连续序列的方法(可以拓展到+,-*,/等).

 将num[i]定义为前i个的异或,则num[i]^num[j]表示序列(i+1,j)的连续异或的值.问题转化为找到j前面的某个i使num[i]^num[j]的值最大.

 朴素的方法为O(n*n),显然会超时,考虑异或的定义,利用字典树就可以在lg(n)内查找,即从高到底,每次查找与当前位不同的前缀.

   关于字典树:

    不知道为神马,用指针写的最后一个点会有runtime error,而本机上可以运行出正确结果.吸取教训以后直接用数组模拟指针= =.

    

你可能感兴趣的:(USACO)