matrix
找规律
题意:给定一个 N*N 的只有 0 和 1 的矩阵,有 Q 个操作,分三种:1. 将某行上的所有数字取反;2. 将某列上的所有数字取反;3. 输出 sum{ a[i][j]*a[j][i] } mod 2。N <=1000,Q<=5*10^5。
解法:初看题目会觉得很棘手。然后可以发现,对于不在对角线上的点,a[i][j]*a[j][i] 会被累加两次(一次是在计算 (i, j) 时,另一次是在计算 (j, i) 时),由同余定理可知,无论 a[i][j] 或 a[j][i] 的值为多少,都不会影响到求余的结果。所以对角线上的 a(i, i) 才是影响结果的关键。当对角线上的 1 的个数为奇数时,答案就为 1;否则为 0。那么我们可以设一个变量 ans,ans 的初始值由扫描初始矩阵得到。每进行一次 1 或 2 操作,就将 ans 取反。遇到 3 操作直接输出即可。
steins
贪心
题意:给出一些顺序排列的长短不一的矩形,宽度都为 1,要用宽度为 1 的刷子进行横向或竖向填充,问最小填充次数使得所有矩形被完全填充。
初步解法:一个只能骗很少部分分的算法:每次选择高度最小的矩形,记其高度为 h,分别向左右进行横向填充,则这一步的填充次数为 h。不断重复此步骤。这种算法完全抛弃了竖向的填充方式,很明显拿不了多少分数。
正解:不算严格意义上的贪心,有点像贪心和动规的结合。对于区间 [l, r],找到区间内的最小高度 h,此时有两种决策:1. 用横向方式填充最短矩形,然后递归两个子区间;2. 用纵向方式填充区间内所有矩形。计算出两种决策分别的花费,取其较小值。
archer
扫描线+线段树
题意:求矩形并的面积。
初步解法:模拟。出题人很良心地给了 30 分。
正解:其实是很经典的题目,之前在书上也看到过类似的求矩形并的周长的方法(POJ 的 Picture 一题),但是从来没写过。
假设有一条扫描线,从左往右扫描,遇到矩形的入边就将其投影到线段树上,遇到矩形的出边就将其从线段树上删去。每次累加扫描到的相邻两条线段的横坐标之差与线段树上的总线段长度的乘积。
上面这段话很笼统,更详细地说:
- 将题目给的每个矩形拆分成左右两条边,记录边的长度、横坐标、是入边还是出边,并将所有边排序;
-
顺序枚举每条边,如果是入边就将其插入到线段树,如果是出边就将其从线段树中删除,具体实现:
- 为线段树的每个结点增加两个域:cover 与 total。cover 表示该线段(注意只是本结点而不包含子树)被完整地覆盖了多少次,total 表示该线段内 cover>0 的线段总长度;
- 每次插入一条线段,就将其对应的线段树结点的 cover 加 1;删除一条线段则反之。那么 cover>0 就表示该结点对应的线段被完全覆盖,则其 total = right-left;如果 cover=0 就表示该结点对应的线段没有被完全覆盖,但是有可能被部分覆盖,则其 total 由左右子树累加得到;
- 插入(删除)一条边后累加答案,累加的值为:本次扫描到的边的横坐标减去上次扫描到的边的横坐标乘以目前线段树中被覆盖的线段总长度,即 ans += (x(i)-x(i-1))*root.total。