Codeforces_846

A.简单dp。

#include<bits/stdc++.h>
using namespace std;

int n,a[105],dp[105][2] = {0};

int main()
{
    ios::sync_with_stdio(0);
    cin >> n;
    for(int i = 1;i <= n;i++)   cin >> a[i];
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        if(a[i] == 0)
        {
            dp[i][0] = dp[i-1][0]+1;
            dp[i][1] = dp[i-1][1];
        }
        else
        {
            dp[i][0] = dp[i-1][0];
            dp[i][1] = max(dp[i-1][0],dp[i-1][1])+1;
        }
    }
    cout << max(dp[n][0],dp[n][1]) << endl;
    return 0;
}
View Code

B.枚举凑满了几个task。

#include<bits/stdc++.h>
using namespace std;

int n,m,k,a[50];

int main()
{
    ios::sync_with_stdio(0);
    cin >> n >> k >> m;
    int sum = 0;
    for(int i = 1;i <= k;i++)
    {
        cin >> a[i];
        sum += a[i];
    }
    sort(a+1,a+1+k);
    int ans = 0;
    for(int i = 0;i <= n;i++)
    {
        int cnt = n-i,left = m-sum*i,now = (k+1)*i;
        if(left < 0)    break;
        for(int j = 1;j <= k;j++)
        {
            if(left < a[j]*cnt)
            {
                now += min(cnt,left/a[j]);
                break;
            }
            now += cnt;
            left -= a[j]*cnt;
        }
        ans = max(ans,now);
    }
    cout << ans << endl;
    return 0;
}
View Code

C.预处理左右两个数的最大值,枚举中间那个点。

#include<bits/stdc++.h>
using namespace std;

int n,l[5005],r[5005];
long long a[5005],sum[5005] = {0},lm[5005],rm[5005];

long long f(int l,int r)
{
    long long t1 = r == 0?0:sum[r-1];
    long long t2 = l == 0?0:sum[l-1];
    return t1-t2;
}

int main()
{
    ios::sync_with_stdio(0);
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        cin >> a[i];
        sum[i] = sum[i-1]+a[i];
    }
    for(int i = 0;i <= n;i++)
    {
        int t;
        long long maxx = -1e18;
        for(int j = 0;j <= i;j++)
        {
            if(f(0,j)-f(j,i) > maxx)
            {
                maxx = f(0,j)-f(j,i);
                t = j;
            }
        }
        l[i] = t;
        lm[i] = maxx;
        maxx = -1e18;
        for(int j = i;j <= n;j++)
        {
            if(f(i,j)-f(j,n) > maxx)
            {
                maxx = f(i,j)-f(j,n);
                t = j;
            }
        }
        r[i] = t;
        rm[i] = maxx;
    }
    long long maxx = -1e18;
    int ans1,ans2,ans3;
    for(int i = 0;i <= n;i++)
    {
        if(lm[i]+rm[i] > maxx)
        {
            maxx = lm[i]+rm[i];
            ans1 = l[i];
            ans2 = i;
            ans3 = r[i];
        }
    }
    cout << ans1 << " " << ans2 << " " << ans3 << endl;
    return 0;
}
View Code

D.二分答案,二维前缀和判断。

#include<bits/stdc++.h>
using namespace std;

int n,m,k,q,mp[505][505];
struct xx
{
    int x,y,t;
    friend bool operator<(xx a,xx b)
    {
        return a.t < b.t;
    }
}a[250005];

bool ok(int t)
{
    memset(mp,0,sizeof(mp));
    for(int i = 1;i <= q && a[i].t <= t;i++)  mp[a[i].x][a[i].y] = 1;
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)   mp[i][j] += mp[i][j-1]+mp[i-1][j]-mp[i-1][j-1];
    }
    for(int i = 1;i <= n-k+1;i++)
    {
        for(int j = 1;j <= m-k+1;j++)
        {
            int endx = i+k-1,endy = j+k-1;
            if(mp[endx][endy]-mp[i-1][endy]-mp[endx][j-1]+mp[i-1][j-1] == k*k)  return 1;
        }
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(0);
    cin >> n >> m >> k >> q;
    for(int i = 1;i <= q;i++)   cin >> a[i].x >> a[i].y >> a[i].t;
    sort(a+1,a+1+q);
    int l = 0,r = 1e9+5;
    while(l < r)
    {
        int mid = (l+r)/2;
        if(ok(mid)) r = mid;
        else    l = mid+1;
    }
    if(l == 1e9+5)  cout << -1 << endl;
    else    cout << l << endl;
    return 0;
}
View Code

E.dfs从下到上处理每个点,注意超long long,负值太大直接NO。

#include<bits/stdc++.h>
using namespace std;

int n,ok = 1;
long long a[100005],b[100005];
struct xx
{
    int to,k;
    xx(int a,int b):to(a),k(b){};
};
vector<xx> v[100005];

void dfs(int now)
{
    for(int i = 0;i < v[now].size();i++)
    {
        int t = v[now][i].to,k = v[now][i].k;
        dfs(t);
        if(a[t] < 0)
        {
            if(1.0*a[t]*k+a[now] < -1e17)   ok = 0;
            a[now] += a[t]*k;
        }
        else    a[now] += a[t];
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin >> n;
    for(int i = 1;i <= n;i++)   cin >> a[i];
    for(int i = 1;i <= n;i++)   cin >> b[i],a[i] -= b[i];
    for(int i = 2;i <= n;i++)
    {
        int x,y;
        cin >> x >> y;
        v[x].push_back(xx(i,y));
    }
    dfs(1);
    if(ok && a[1] >= 0) cout << "YES" << endl;
    else    cout << "NO" << endl;
    return 0;
}
View Code

F.记录每一个值的上一个位置,就容易计算每个点加入时增加的总价值。

#include<bits/stdc++.h>
using namespace std;

int n,a[1000005],la[1000005] = {0};

int main()
{
    ios::sync_with_stdio(0);
    cin >> n;
    for(int i = 1;i <= n;i++)   cin >> a[i];
    long long ans = 0;
    for(int i = 1;i <= n;i++)
    {
        long long t1 = i-la[a[i]],t2 = n-i+1;
        ans += t1*t2;
        la[a[i]] = i;
    }
    ans *= 2;
    ans -= n;
    cout << fixed << setprecision(10) << 1.0*ans/n/n << endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/zhurb/p/7486543.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值