2.4 综合训练

A.Maximum Subrectangle(赛时完成)

题意:求满足矩阵权值和 <= x ,且矩阵面积最大

思路:矩阵权值和 = 横区间和 * 纵区间和

   预处理每个长度的最小区间和,对于每个长度的横区间和,二分查找最长符合条件纵区间和,对所有计算结果取max

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
const int inf = 0x3f3f3f3f;
ll arr[maxn];
ll brr[maxn];
ll la[maxn], lb[maxn];
int main()
{
    ll n, m ,x;
    scanf("%lld %lld", &n, &m);
    arr[0] = brr[0] = 0;
    memset(la, inf, sizeof la);
    memset(lb, inf, sizeof lb);
    for (int i = 1; i <= n; ++i)
    {
        scanf("%lld", &arr[i]);
        arr[i] = arr[i] + arr[i - 1];
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = i; j <= n; ++j)
        {
            la[j - i + 1] = min(la[j - i + 1], arr[j] - arr[i - 1]);
        }
    }
    for (int i = 1; i <= m; ++i)
    {
        scanf("%lld", &brr[i]);
        brr[i] = brr[i] + brr[i - 1];
    }
    scanf("%lld", &x);
    for (int i = 1; i <= m; ++i)
    {
        for (int j = i; j <= m; ++j)
        {
            lb[j - i + 1] = min(lb[j - i + 1], brr[j] - brr[i - 1]);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            if (la[i] * lb[j] <= x) ans = max(ans, i * j);
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

B.Mouse Hunt(赛后完成)

题意:在房间中布置陷阱,询问无论老鼠从地出发都能被抓到的最小花费

思路:每个连通块都是n点n边出度为1,因此对于每个连通块必定有环,且连通块路径有且只有一条,dfs跑环,找到环上权值最小的点,计算所有连通块的环上权值最小点的和

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 100;
const int inf = 0x3f3f3f3f;
int val[maxn] ,to[maxn];
int vis[maxn] ,vis1[maxn];
int dfs(int rt)
{
    if (vis[rt] != 0) return 0;
    vis1[rt]++;
    int ans = inf;
    if (vis1[rt] == 2)
    {
        if (to[rt] == rt) ans = val[rt];
        ans = min(ans, val[rt]);
        for (int i = to[rt]; i != rt; i = to[i])
        {
            ans = min(ans, val[i]);
        }
        return ans;
    }
    
    ans = min(ans, dfs(to[rt]));
    vis[rt] = 1;
    return ans == inf ? 0 : ans;
}
// n点n边且出度都为1 , 所以每个连通块必定有环 , 而且路径有且仅有一条
int main()
{
    int n;
    memset(vis, 0, sizeof vis);
    memset(vis1, 0, sizeof vis1);
    scanf("%d", &n);
    int sum = 0;
    for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &to[i]);
    for (int i = 1; i <= n; ++i)
    {
        if (vis[i] == 0)
        {
            sum += dfs(i);
        }
    }
    printf("%d\n", sum);
    return 0;
}
View Code

C.Psychos in a Line(赛后完成)

题意:arr[i] > arr[i + 1] 第i个数字就可以把第i+1个数字消除掉,询问消除到没有数字可以消除所需要的步数

思路:用单调栈从后往前维护一个单调递增栈,用dp[i]来维护i消除所有能够消除的数字所需要的最大步数

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
const int inf = 0x3f3f3f3f;
int arr[maxn];
int ans[maxn];
stack<int>s;
int main()
{
    int n;
    scanf("%d", &n);
    memset(ans, 0, sizeof ans);
    for (int i = 1; i <= n; ++i) scanf("%d", &arr[i]);
    for (int i = n; i >= 1; --i)
    {
        if (s.empty())
        {
            s.push(i);
            ans[i] = 0;
            continue;
        }
        if (arr[s.top()] > arr[i])
        {
            ans[i] = 0;
            s.push(i);
        }
        else
        {
            ans[i] = max(1, ans[s.top()]);
            // 第i个人肯定能杀死第s.top()个人
            s.pop();
            while (s.size() && arr[i] > arr[s.top()])
            {
                ans[i] = max(ans[i] + 1, ans[s.top()]);
                s.pop();
            }
            s.push(i);
        }
    }
    int val = 0;
    for (int i = 1; i <= n; ++i)
    {
        val = max(val, ans[i]);
        //printf("%d ", ans[i]);
    }
    //cout << endl;
    printf("%d\n", val);
    return 0;
}
View Code

D.Sequence Sorting(未完成)

E.Lucky Transformation(赛时完成)

题意:对于 i % 2 == 1 && arr[i] == 4 && arr[i + 1] == 7 ,arr[i + 1] = 4

      i % 2 == 1 && arr[i] == 4 && arr[i + 1] == 4 ,arr[i + 1] = 7

思路:按题意模拟,考虑好特殊情况就行了

#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn = 1e5 + 100;
int arr[maxn];

int main()
{
    int n , k;
    scanf("%d %d", &n,&k);
    for (int i = 1; i <= n; ++i) scanf("%1d", &arr[i]);
    arr[0] = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (k == 0) break;
        if (arr[i - 1] == 4 && arr[i] == 4 && arr[i + 1] == 7 && i % 2 == 0)
        {
            if (k % 2 == 1) arr[i] = 7;
            k = 0;
            break;
        }
        else if(arr[i - 1] == 4 && arr[i] == 7 && arr[i + 1] == 7 && i % 2 == 0)
        {
            if (k % 2 == 1) arr[i] = 4;
            k = 0;
            break;
        }
        else if (arr[i] == 4 && arr[i + 1] == 7 && i % 2 == 1)
        {
            arr[i + 1] = 4;
            k--;
        }
        else if (arr[i] == 4 && arr[i + 1] == 7 && i % 2 == 0)
        {
            arr[i] = 7;
            k--;
        }
    }
    for (int i = 1; i <= n; ++i)
    {
        printf("%d", arr[i]);
    }
    printf("\n");
    return 0;
}
View Code

F.President's Path(未完成)

posted @ 2020-02-05 10:22  当然是斗笠呀  阅读(133)  评论(0编辑  收藏  举报