Codeforces Round #695 (Div. 2)

原题链接:https://codeforces.com/contest/1467

A. Wizard of Orz

A题就WA了两发才过,真是令人难受

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int k=9;
        while(n--)
        {
            cout<<k;
            k-=1;
            if(k==-1) k=9;
        }
        cout<<endl;
    }
    return 0;
}
View Code

B. Hills And Valleys

B题自己写模拟写的心态爆炸,道理很简单,就是写不对,最后还是大佬的题解思路清晰

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=3e5+10;
int a[maxn];
int n;
int f(int x)
{
    if(x==1||x==n) return 0;
    if(a[x-1]<a[x]&&a[x+1]<a[x]) return 1;
    if(a[x-1]>a[x]&&a[x+1]>a[x]) return 1;
    return 0;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int ans=0;
        for(int i=2;i<n;i++)
        {
            if(a[i-1]<a[i]&&a[i+1]<a[i]) ans++;
            if(a[i-1]>a[i]&&a[i+1]>a[i]) ans++;
        }
        int sum=0;
        for(int i=2;i<n;i++)
        {
            int flag=a[i];
            int ans1=f(i-1)+f(i)+f(i+1);
            a[i]=a[i-1];
            int ans2=f(i-1)+f(i)+f(i+1);
            a[i]=a[i+1];
            int ans3=f(i-1)+f(i)+f(i+1);
            a[i]=flag;
            sum=max(sum,max(ans1-ans2,ans1-ans3));
        }
        cout<<max(0,ans-sum)<<endl;
    }
    return 0;
}
View Code

C. Three Bags

题意:有三个背包,里面各自装了数, 每次可以选择任意两个非空背包,取其中一个数a和b 然后变成a-b放回 a背包中,b背包中的该数消失 直到最后只剩下一个数, 问剩下的数最大为多少

思路:考虑最后所有的数都会归到一个数的身上,这个数给的贡献不是正数就是负数,取决于中间走了几步

奇数为负数,偶数为正数, 所有最后的答案是总的sum-2*sub , ×2是为了抵消掉负数加进去sum的贡献

那么就只有几种情况:

要么是某两个背包的最小的数来作为跳板

要么是只用某一个背包的最小数来作为跳板变成正数,然后这一个背包的数 全部当作负数贡献

#include<iostream>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
int a[maxn],b[maxn],c[maxn];
ll d[10];
int main()
{
    int n1,n2,n3;
    ll sum1=0,sum2=0,sum3=0;
    cin>>n1>>n2>>n3;
    for(int i=1;i<=n1;i++) scanf("%d",&a[i]),sum1+=a[i],a[1]=min(a[i],a[1]);
    for(int i=1;i<=n2;i++) scanf("%d",&b[i]),sum2+=b[i],b[1]=min(b[i],b[1]);
    for(int i=1;i<=n3;i++) scanf("%d",&c[i]),sum3+=c[i],c[1]=min(c[i],c[1]);
    ll ans=sum1+sum2+sum3;
    ll flag=1e17;
    d[1]=flag;
    d[2]=sum1;
    d[3]=sum2;
    d[4]=sum3;
    d[5]=a[1]+b[1];
    d[6]=a[1]+c[1];
    d[7]=b[1]+c[1];
    for(int i=1;i<=7;i++) d[1]=min(d[i],d[1]);
    cout<<ans-2*d[1]<<endl;
    return 0;
}
View Code

D. Sum of Paths

先预处理出所有走法每个格子会被走的次数总和

 dp[i][j]dp[i][j] 表示第 j步走到第 i个格子的情况数量

初始化 dp[i][0]=1

转移方程 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i + 1 ] [ j − 1 ] ,即通过一步从相邻格子转移来;

那么走 j步恰好到达第 i 个格子的情况数为 d p [ i ] [ j ] ,但是一共要走 k 步

从第 i 个格子走 k − j 步的情况数量等于从任意格子走 k − j 步恰好到达第i 个格子的情况,即 d p [ i ] [ k − j ],所以次数贡献就是 d p [ i ] [ j ] ⋅ d p [ i ] [ k − j ]

知道每个格子的贡献次数,那么改变一个格子就可以 O ( 1 )  算出了。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=5e3+10;
ll a[maxn];
ll dp[maxn][maxn];
ll cnt[maxn];
int main()
{
    int n,k,q;
    cin>>n>>k>>q;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i][0]=1;
    for(int j=1;j<=k;j++)
        for(int i=1;i<=n;i++)
            dp[i][j]=(dp[i-1][j-1]+dp[i+1][j-1])%mod;
    for(int j=0;j<=k;j++)
        for(int i=1;i<=n;i++)
            cnt[i]=(cnt[i]+dp[i][j]*dp[i][k-j])%mod;
    ll ans=0;
    for(int i=1;i<=n;i++) ans=(ans+cnt[i]*a[i])%mod;
    int id,x;
    while(q--)
    {
        scanf("%d%d",&id,&x);
        ans=(ans+(x-a[id]+mod)%mod*cnt[id])%mod;
        printf("%lld\n",ans);
        a[id]=x;
    }
    return 0;
}
View Code

 

posted @ 2021-01-24 11:09  standard_zsz  阅读(106)  评论(0)    收藏  举报