1. 程式人生 > 其它 >2022.3.7

2022.3.7

藍書

AcWing 100. IncDec序列

思路:一開始想的是每個數都減去一個數,以為是平均值,後面想到差分就讓每個數減去它前面一個構造了差分陣列,因為我們最終是要讓序列的每一個數都一樣,所以我們讓b[1]=a[1],讓b[2-n]變成0,預處理出2-n的正數和z和負數和f,一部分的操作次數就是現在z和f消去一部分即min(z,f),剩下一部分我們考慮與a[1]相消去,於是答案為min(z,f)+abs(z-f),這裡有abs(z-f)+1種排列方式,+1是因為z和f可能相等,那麼a[1]本身就是一種排列方式了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10,INF=1e8;
ll a[N],b[N],n;
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n;i++)
        scanf("%lld",&a[i]);
    b[1] = a[1];
    ll z = 0, f = 0,ans=0;
    for (int i = 2; i <= n;i++)
    {
        b[i] = a[i] - a[i - 1];
        if(b[i]>0)
            z += b[i];
        else
            f -= b[i];
    }
    ans += min(z, f)+abs(z-f);
    printf("%lld\n%lld", ans, abs(f - z) + 1);
    return 0;
}

AcWing 101. 最高的牛

思路:如果兩頭牛要相互看的見的話它們之間的牛的身高必須都小於他們,於是我們對每次輸入的牛讓它們之間的牛身高都-1,利用差分陣列記錄一下每對牛之間的相對關係,最後轉化成字首和再加上最高的牛的身高。
一開始判重用的是int陣列結果超記憶體了,改用map就過了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int N=1e4+10,INF=1e8;
map<pair<int, int>,int> mp;
int ans[N];
int main()
{
    int n, p, h, m;
    scanf("%d%d%d%d", &n, &p, &h, &m);
    for (int i = 1; i <= m;i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        if(a>b)
            swap(a, b);
        if(mp[{a,b}])
            continue;
        mp[{a,b}] = 1;
        ans[a + 1]--;
        ans[b]++;
    }
    for (int i = 1; i <= n;i++)
    {
        ans[i] +=ans[i-1];
        printf("%d\n", ans[i]+h);
    }
    return 0;
}

AcWing 102. 最佳牛圍欄

思路:要求平均值*1000,應該用浮點數二分,為了簡便計算,對於每個數我們都先減去二分的平均值,這下問題可以轉化成在一個序列中求長度不超過L的非負子段和。因為每塊地最多也就只有2000頭牛,假設每塊地都有2000頭牛的話,那麼二分答案的最大值也就是2000,因此可以縮小二分的範圍,在二分的過程中,我們不必列舉每次的最小值,只需要在i增長的過程中記錄下當前的最小值就可以,同時不斷更新答案:b[i]-mmin。
一開始減平均值的時候想錯了,沒在二分的時候減。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10,INF=1e8;
int n, m;
double a[N], b[N];
int check(double mid)
{
    double mmin = INF, mmax = -INF;
    for (int i = 1; i <= n;i++)
        b[i] = b[i - 1] + a[i] - mid;
    for (int i = m; i <= n;i++)
    {
        mmin = min(mmin, b[i - m]);
        mmax = max(mmax, b[i] - mmin);
    }
    return mmax >= 0;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n;i++)
    {
        scanf("%lf", &a[i]);
    }
    double l = 0, r = 2000;
    while(r-l>1e-5)
    {
        double mid = (l + r) / 2;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    printf("%d", int(r * 1000));
    return 0;
}