2009081701 模拟题解 | 二维前缀和+二分答案/dp | 贪心

T1

1 crf 的视察
1.1 Description
crf 拥有一个王国。
他的王国是长方形的,跨越了 n 个纬度区和 m 个经度区,且在每个经度区和纬度区的交界处
有一座城市(即 crf 的王国一共有 n
×
m 座城市)。
某一天早上,crf 从他的一万平方米的大床上起来,他决定去视察一下他的王国,去查看一下
他的全民刷题计划的实施情况。
消息一出,全王国各城市的市长们都吓到了,因为有一些市长偷懒还没有宣布 crf 的全民刷题
计划,所以全体市长集体开了个会,讨论要怎样才能让 crf 不发现他们的不作为。
他们知道 crf 有个坏习惯,他只会视察一个正方形区域的城市,而他们也知道视察了越多的城
市,crf 就会越开心。但一旦 crf 发现他视察的城市他的政策没有贯彻下去,他就会非常愤怒,然后
把这些市长发配去养猪。
市长们现在想找出来一个最大正方形,使得在这个正方形内的所有城市都已经贯彻了 crf 的全
民刷题计划。
1.2 Input
输入的第一行为两个整数 n, m,表示 crf 王国横跨的纬度区数量和经度区数量。
接下来 n 行,每行有 m 个整数,每个整数只可能为 0 或者 1,0 表示这个城市没有贯彻 crf 的
全民刷题计划,1 表示已经贯彻。
1.3 Output
输出一个数字 k,为最大的正方形的边长。
1.4 Sample
Sample Input Sample Output
3 3
0 1 1
1 1 1
1 1 1
2
1.5 Hint
对于 30% 的数据,保证 1
n, m
30。
对于 100% 的数据,保证 1
n, m
2000。
 
题解:
一、二维前缀和+二分答案+快读 卡常o(n^2logn)100分
二、dp[i][j]表示,第i行第j个格子作为左上角能画出的最大的正方形的边长
首先o(n)求出dp[1][1](枚举i = j = 上一次+1,找符合的最大i,j)
然后dp初值为dp[i][j] = max(dp[i - 1][j],max(dp[i - 1][j - 1],dp[i][j - 1])) - 1,之前的收缩一个可变为以i,j为左上角的可能的正方形,然后再枚举对角线延长线上的点,找符合的最大边长,由于每次dp只会减少一,每一行dp会减少n次,而dp最大值为一,所以最多只会多枚举2n次,而不是n^2次,所以复杂度为o(n^2)
三、dp[i][j]表示,第i行第j个格子作为右下角能画出的最大正方形的边长
在输入的时候就可以处理dp,若这个点为1,则dp[i][j] = min(dp[i - 1][j],min(dp[i - 1][j - 1],[dp[i]][j  -1 ])) + 1;(因为中间可能有空格子,所以得取min而不是max),复杂度o(n^2)
 
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a[2005][2005];
 5 int b[2005][2005];
 6 int n,m;
 7 int check(int k)
 8 {
 9     for(int i = 1; i <= n; i ++)
10     {
11         if(i + k - 1 > n || i + k - 1 < 1)continue;
12         for(int j = 1; j <= m; j ++)
13         {
14             if(j + k - 1 > m || j + k - 1 < 1)continue;
15             int mid = b[i + k - 1][j + k - 1] - b[i - 1][j + k - 1] - b[i + k - 1][j - 1] + b[i - 1][j - 1];
16             //printf("mmmmmmm%d %d %d %d-%d-%d+%d=%d\n",i,j,k,b[i + k - 1][j + k - 1],b[i - 1][j],b[i][j - 1],b[i - 1][j - 1],mid);
17             if(mid == k * k)
18             {
19                 return 1;
20             }
21         }
22     }
23     return 0;
24 }
25 int main()
26 {
27     freopen("inspect.in","r",stdin);
28     freopen("inspect.out","w",stdout);
29     scanf("%d%d",&n,&m);
30     for(int i = 1; i <= n; i ++)
31     {
32         for(int j = 1; j <= m; j ++)
33         {
34             scanf("%d",&a[i][j]);
35             b[i][j] = b[i - 1][j] + b[i][j - 1] + a[i][j] - b[i - 1][j - 1];
36         }
37     }
38     int l = 0,r = min(n,m),mid;
39     while(l <= r)
40     {
41         mid = (l + r) / 2;
42         if(check(mid))l = mid + 1;
43         else r = mid - 1;
44     }
45     printf("%d",r);
46     return 0;
47 }
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<queue>
 7 #include<map>
 8 #include<string>
 9 using namespace std;
10 int n,m,ans;
11 bool vis[2005][2005];
12 int sum[2005][2005];
13 int main()
14 {
15     freopen("inspect.in","r",stdin);
16     freopen("inspect.out","w",stdout);
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=n;i++)
19     {
20         for(int j=1,x;j<=m;j++)
21         {
22             scanf("%d",&x);
23             if(x)
24             {
25                 vis[i][j]=1;
26                 sum[i][j]=min(sum[i-1][j-1],min(sum[i-1][j],sum[i][j-1]))+1;
27                 ans=max(ans,sum[i][j]);
28             }
29         }
30     }
31     printf("%d",ans);
32     return 0;
33 }

 

T2

2 crf 的军训
2.1 Description
crf 在拥有他的王国之前,还是一名中国人,在中国读完了大学。
众所周知,中国籍学生在中国读大学是要参加军训的,即使是 crf 这样的天才也不能避免。
并且,众所周知,如果你运气不好上了一些军训很严的大学,你就会被要求做一些非常奇怪的
事情。而 crf 就是上了这样奇怪的大学。
军训的第一天,教官就检查了 crf 的寝室内务。教官对于 crf 的书架非常不满。crf 的教官是一
个强迫症非常严重的人,他要求 crf 把书架里的书按层整理,每一层的书都要按从大到小的顺序放,
后一本书的长宽都不能超过前一本书。
crf 发现这个事情其实非常麻烦,因为他的书架只有三层,而他的书非常多,很有可能需要十
多层甚至几十层才能放下他的书,这意味着他必须要上当时的首富(现在的首富当然是 crf 啦)家
的网站去买一大堆书架。
crf 想知道,他最少需要多少层书架,才能放下他的全部的书。全知全能的 crf 当然能在 1ns 内
算出这个问题,但他非常珍惜他的时间,甚至为此戴上了黑框眼镜。所以他想让你帮他算这个问题,
然后他就可以上网买书架了。
2.2 Input
第一行为一个整数 n,表示 crf 拥有的书的数量。
之后 n 行,每行有两个整数 x, y,表示这本书的长宽。
2.3 Output
输出一个数字 k,表示 crf 至少需要 k 层书架才能按照教官的要求摆放下他的所有书。
2.4 Sample
Sample Input Sample Output
5
1 1
1 2
2 1
2 2
2 3
2
2.5 Hint
对于 30% 的数据,满足 1
n
10。
对于 100% 的数据,满足 1
n
300。 
 
题解:
一、用导弹拦截的第二问的做法求
二、贪心做法:
先将长排个序,再逐个比较宽,若这个宽小于每一组的最大值,就再开一个组
 1 //将l排序,再逐个比较w,若<每个组的最大值,就再开一个组 
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 struct node
 6 {
 7     int l,w;
 8 }a[1005];
 9 bool cmp(node x,node y)
10 {
11     if(x.l == y.l)return x.w < y.w;
12     return x.l < y.l;
13 }
14 bool cmpp(node x,node y)
15 {
16     if(x.w == y.w)return x.l < y.l;
17     return x.w < y.w;
18 }
19 bool cmppp(int x,int y)
20 {
21     return x > y;
22 }
23 int b[1005],c[1005],cnt[1005],m[1005],ans,flag;
24 int main()
25 {
26     freopen("militarytraining.in","r",stdin);
27     freopen("militarytraining.out","w",stdout);
28     int n;
29     scanf("%d",&n);
30     for(int i = 1;i <= n;i ++)
31     {
32         scanf("%d %d",&a[i].l,&a[i].w);
33     }
34     sort(a + 1,a + 1 + n,cmp);
35     flag = 0;
36     for(int i = 1;i <= n;i ++)
37     {
38         flag = 0;
39         for(int j = 1;j <= ans;j ++)
40         {
41             if(a[i].w >= m[j])
42             {
43                 m[j] = a[i].w;
44                 flag = 1;
45                 break;
46             }
47         }
48         if(flag == 0)
49         {
50             ans ++;
51             m[ans] = a[i].w;
52         }
53     }
54     printf("%d",ans);
55     return 0;
56 }

 

T3

3 crf 的数数
3.1 Description
crf 从小就显现出了过人的天赋,他出生的第三天就证明了哥德巴赫猜想,第五天就证明了质
能方程,出生一星期之后,他觉得 P 是否等于 NP 这个问题比前面他证明的这些定理好玩多了,于
是他成为了一名计算机科学家。
在他开始接触计算机科学的第一天,他就已经刷遍了所有 oj,这为他今后建立王国推行全民刷
题计划打下了坚实的基础。在他接触计算机科学一星期之后,他就已经通读了所有顶会 paper,并
且在多方面同时出了许多成果。
他对他王国的国民智商有非常高的要求,他为想加入他的王国国籍的人准备了很多试题去测试
智商,但因为他接触计算机科学第一天学到的东西就已经超过正常人一生的水平了,所以他出的试
题水平在他接触计算机科学 1 分钟以内的水平。
这道题是 crf 接触计算机科学第 17 秒想出的问题。
crf 拥有一个长度为 n 的数字序列,他向你询问了 q 个问题,每个问题都是告诉你两个数 l 和
r,问你在序列的第 l 到第 r 个数的这一段序列中,有多少个数字 k,满足在这一段中恰好出现了 k
次。
3.2 Input
输入的第一行为两个整数 n, q,表示序列的长度和问题的个数。
接下来一行有 n 个整数,表示 crf 的数字序列。
接下来 q 行,每行有两个整数 l, r,其含义如题目中所示。
3.3 Output
输出共 q 行,每行有一个整数,表示第 i 个问题的答案。
Sample Input Sample Output
7 2
3 1 2 2 3 3 7
1 7
3 4
3
1
3.4 Hint
对于 30% 的数据,保证 1
n, q
100。
对于 70% 的数据,保证 1
n, q
100000。
对于 100% 的数据,保证 1
n, q
1000000, 序列中的每个数都在 [1, n] 范围内。 
 

 

posted @ 2019-11-09 20:06  djfuuxjz  阅读(19)  评论(0编辑  收藏  举报