• HZNU Training 2 for Zhejiang Provincial Competition 2020


    A - Largest Submatrix of All 1’s

     POJ - 3494

    题意:给一个只包含0和1的n*m的矩形,求由‘1’围成的最大矩形的面积。

    分析:单调栈的应用,对n行每一行处理,可转化为POJ - 2559求最大矩形的面积。注意点:如果加入的元素破坏了非单调递减,清栈之后要把栈顶元素值更新为新加入的元素。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn = 2005;
     6 typedef long long ll;
     7 int nums[maxn][maxn];
     8 int st[maxn];
     9 int main(){
    10     int n,m;
    11     while (~scanf("%d%d",&n,&m)){
    12         memset(nums,0,sizeof nums);
    13         for (int i = 1; i <= n; i++){
    14             for (int j = 1; j <= m; j++){
    15                 scanf("%d",&nums[i][j]);
    16             }
    17         }
    18         for (int i = 1; i <= n; i++){
    19             for (int j = 1; j <= m; j++){
    20                     if (nums[i][j]) nums[i][j] += nums[i-1][j];
    21             }
    22         }
    23         ll s = 0;
    24         for (int i = 1; i <= n; i++){
    25             int top = 0; 
    26             memset(st,0,sizeof st);
    27             nums[i][m+1] = -1;
    28             for (int j = 1; j <= m+1; j++){
    29                 if (top == 0 || nums[i][j] >= nums[i][st[top-1]]) {
    30                     st[top++] = j;
    31                 }
    32                 else{
    33                     int pos; 
    34                     while (top && nums[i][st[top-1]] > nums[i][j]){
    35                         pos = st[top-1];
    36                         s = max(s,(ll)(j-st[top-1])*(ll)nums[i][st[top-1]]);
    37                         top--;
    38                     }
    39                     st[top++] = pos;
    40                     nums[i][pos] = nums[i][j];//关键点                
    41                 }
    42             }
    43         }
    44         printf("%lld
    ",s);
    45     }
    46     return 0;
    47 }
    View Code

    B - Ayoub's function

     CodeForces - 1301C 

    题意:给一个长度为n的01串,含有m个1,求如何组合能使含1子区间数最多,输出最多数量。

    分析:总含1子区间数 = 总子区间数 - 总连续0子区间数,要使答案最大,总连续0子区间数要最少。最优方案(不作证明)是把所有0均分区间,注意:剩下的0不能全部给一个区间,也要均分到每个区间。此外当m>=n/2时最优解一定为0和1交替分配,剩下的1随意分配,可以直接计算得答案减少一半的枚举次数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int main(){
     5     int T;
     6     ll n, m;
     7     scanf("%d", &T);
     8     while (T--) {
     9         scanf("%lld%lld",&n,&m);
    10         if (m==0) puts("0");
    11         else if (m>=(n/2)){
    12             printf("%lld
    ",m+(n-1)*n/2);
    13         }
    14         else{
    15             ll nums = (n-m)/(m+1),l = (n-m)%(m+1);
    16             printf("%lld
    ",n*(n+1)/2-l*(nums+1)*(nums+2)/2+(m+1-l)*nums*(nums+1)/2);
    17         }
    18     }
    19     return 0;
    20 }
    View Code

    C - Managing Difficulties

     Gym - 102411M

    题意:求数组中任意三个数构成等差数列的组数。

    分析:枚举起点、中点、终点之中任意2个,理论上通过这两个点可以推得第三个数,只需查询并统计所有第三个数的数量。给的时间2s,组数 t <= 10,n <= 2000,枚举两个点需要O(n^2)的复杂度,单看n时间是足够的,但数组中的数可以达到1e9,有些方案使用map可以卡着时间过,但注意到n只有2000,十分明显可以离散化处理优化时间复杂度,离散化后对该题给的数据时间可以降低3倍以上,但使用离散化对枚举的点有特殊要求,具体看代码实现。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 2005;
     4 typedef long long ll;
     5 int ans,m,n,t;
     6 ll arr[maxn],a[maxn],b[maxn];
     7 int mp[maxn];
     8 inline ll read() {
     9     char ch = getchar(); ll x = 0, f = 1;
    10     while(ch < '0' || ch > '9') {
    11         if(ch == '-') f = -1;
    12         ch = getchar();
    13     } while('0' <= ch && ch <= '9') {
    14         x = x * 10 + ch - '0';
    15         ch = getchar();
    16     } return x * f;
    17 }
    18 int get(ll x){
    19     int pos = lower_bound(b+1,b+1+m,x)-b;
    20     if (b[pos]!=x) pos = 0;
    21     return pos; 
    22 }
    23 int main(){
    24     scanf("%d",&t);
    25     while (t--){
    26         ans = 0,m = 0;
    27         scanf("%d",&n);
    28         for (int i = 1; i <= n; i++){
    29             a[i] = b[i] =  read();
    30         }
    31         sort(b+1,b+1+n);
    32         m = unique(b+1,b+1+n)-b-1;
    33         for (int i = 1; i <= n ;i++)
    34         arr[i] = lower_bound(b+1,b+1+m,a[i])-b,mp[arr[i]]++;
    35         
    36         for (int i = 1; i <= n; i++){
    37             mp[arr[i]]--;
    38             for (int j = i+1; j <= n; j++){
    39                 mp[arr[j]]--;
    40                 ll tmp = 2*a[j]-a[i];
    41                 if (tmp>=1&&tmp<=b[m]) ans += mp[get(tmp)];
    42             }
    43             for (int j = i+1; j <= n; j++) mp[arr[j]]++;
    44         }
    45         for (int i = 0; i <= m; i++) mp[i] = 0;
    46         printf("%d
    ",ans);
    47     }
    48     return 0;
    49 }
    View Code

    F - Binary String Minimizing

     CodeForces - 1256D

    题意: 给一个长度为n的01串,能够把相邻的两个数交换k次,输出交换完后最小字典序的01串。

    分析:把0尽可能往前放,可以从字符串第一个位置开始枚举,只要移动次数够就把0移到那个位置,不够就往前移剩余移动次数次。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int main(){
     5     string str;
     6     ll q,k,n;
     7     cin>>q;
     8     while (q--){
     9         cin>>n>>k>>str;
    10         ll cnt = 0;
    11         for (ll i = 0; i < n; i++){
    12             if (str[i] == '0'){
    13                 if (i-cnt <= k) k -= i-cnt,swap(str[i],str[cnt++]);
    14                 else swap(str[i],str[i-k]),k = 0;
    15             }
    16             if (!k) break;
    17         }
    18         cout<<str<<endl;
    19     }
    20     return 0;
    21 }
    View Code

    H - A Simple Math Problem

     HDU - 5974

    题意:给a,b,找满足条件x+y = a,lcm(x,y)= b的x、y,找不到输出No Solution。

    分析:lcm(x,y) = x * y / gcd(x,y)  = b 易证 gcd(a,b) = gcd(x,y),2个未知数2个方程可以直接把x和y算出来,如果不是整数输出No Solution即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 inline ll gcd(ll a, ll b) {
     5     return b == 0 ? a : gcd(b, a%b);
     6 }
     7 int main(){
     8     ll a,b,X,Y;
     9     while (~scanf("%lld %lld",&a,&b)){
    10         double y = (a-sqrt(a*a-4*b*gcd(a,b)))/2;
    11         if (y == (ll)y) {
    12             Y = y;
    13             if (Y <= a-Y)
    14             printf("%lld %lld
    ",Y,a-Y);
    15             else
    16             printf("%lld %lld
    ",a-Y,Y);
    17         }
    18         else printf("No Solution
    ");
    19     }
    20     return 0;
    21 }
    View Code
  • 相关阅读:
    什么是P问题、NP问题和NPC问题
    Ubuntu 14.04 亮度BUG解决方案
    彻底理解Java中this指针
    Eclipse快捷键大全
    JAVA文件读写方法和性能比较总结
    Java下static关键字用法详解
    LeetCode: Gray Code
    LeetCode: 4sum
    LeetCode:3Sum Closest
    LeetCode:Remove Element
  • 原文地址:https://www.cnblogs.com/hznudreamer/p/12424139.html
Copyright © 2020-2023  润新知