Codeforces Round #526(Div.2)

毒瘤题面(我英语好差啊=。=)

A题:

题解:

题面讲有一个电梯从x楼开始要接i楼的人从i楼到1楼 再从1楼到i楼 但是这个电梯很鬼,每次送完人都要回到x楼。问这个电梯一天要上下几楼。

看一眼数据范围n<=100 于是枚举x 然后枚举楼层 求答案取最小。 复杂度n方

题面:https://codeforces.com/contest/1084/problem/A

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
char str[N];
int a[120];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int ans=INF,res;
    for(int i=1;i<=n;i++){
        res=0;
        for(int j=1;j<=n;j++){
            res+=2*(abs(i-j)+j-1+i-1)*a[j];
        }
        ans=min(ans,res);
    }
    printf("%d\n",ans);
    return 0;
}

B题:

(表示一开始真的看不懂题目在说啥)

题解:

题目给了n杯vi升的什么东西,然后让你接s升的什么东西,要求接完后最少杯子中的东西最多能是多少

这个题先求一遍∑vi 然后将结果减去s 就是剩下的 假设他能平均分配 于是最少的最多就是 (∑vi-s)/n。

当然如果有个杯子本来就小于之前求的值,那么最小的最大就是min(min(vi),(∑vi-s)/n)

题面:https://codeforces.com/contest/1084/problem/B

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
char str[N];
long long a[1200];
int main(){
    long long n,m,sum=0,minn=INF;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum+=a[i];
        if(minn>a[i]) minn=a[i];
    }
    if(sum<m){
        puts("-1");
    }
    else {
        sum-=m;
        if(sum%n==0){
            if(minn<sum/n) sum=minn;
            else sum=sum/n;
            printf("%lld\n",sum);
        }
        else {
            if(minn<sum/n) sum=minn;
            else sum=sum/n;
            printf("%lld\n",sum);
        }
    }
    return 0;
}

C题:

题解:

题意是给你一个字符串在其中有序的选一些集合保证对于每个元素都是‘a’,且每个元素在原串中的位置之间存在‘b’。

想到可以将原串预处理成几个块,满足每个块之间能相互连接,块之间的元素不能相互连接,即块与块之间的a中必定存在‘b’,这样我们对于答案就可从第一个块枚举到最后一个块,没遍历一个块讲答案加上答案本身*块中a的个数并加上块中a个数的本身

即 sum+=(sum*que[i])%mod+que[i];  sum%=mod;

(可以理解为当前块的每个元素都可以与前面的任何一个答案进行连接再加上单独当前块)

题面:https://codeforces.com/contest/1084/problem/C

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
char str[N];
long long que[N];
int tot;
int arr[N],pp[N],wei[N];
int main(){
    scanf("%s",str);
    tot=0;
    int len=strlen(str);
    int tmp=0;
    for(int i=0;i<len;i++){
        if(str[i]=='a'){
            tmp++;
        }
        else if(str[i]=='b'){
            que[++tot]=tmp;
            tmp=0;
        }
    }
    if(tmp!=0) que[++tot]=tmp;
    long long sum=0;
    for(int i=1;i<=tot;i++){
        sum+=(sum*que[i])%mod+que[i];
        sum%=mod;
    }
    printf("%lld\n",sum);
    return 0;
}

D:

题解:

题意是求一棵树上的一段直径其点权-边权值最大

可以想到是一个树上求最大直径的dp(wannfly敦敦敦讲过=。=)

维护数据d[N]代表该节点流通其子节点的最大直径

对于一个节点 其直径最大的线段若经过这个节点 那么可以是以下几种情况

1.只有这一个点d[x]=a[x];

2.与一最大的子节点相连即d[x]=max(d[x],d[x]+d[y]-wei[i]) 注:y为子节点,wei[i]为x到y的边权

3.其次大子节点与最大子节点通过x相连(用于更新答案,不用于更新d[x]值)ans=max(ans,a[x]+tmp1+tmp2)

题面:https://codeforces.com/contest/1084/problem/D

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
char str[N];
int head[N];
int NEXT[3*N],ver[3*N];
long long wei[3*N];
long long dp[N],a[N];
int n,tot;
long long ans;
void init(){
    tot=1;
    ans=0;
    memset(head,-1,sizeof(head));
}
long long Max(long long a,long long b){
    if(a>b) return a;
    return b;
}
void link(int u,int v,int w){
    ver[++tot]=v;
    NEXT[tot]=head[u];
    head[u]=tot;
    wei[tot]=w;
    ver[++tot]=u;
    NEXT[tot]=head[v];
    head[v]=tot;
    wei[tot]=w;
}
void dfs(int x,int pre){
    dp[x]=a[x];
    long long res=0,rres=0;
    for(int i=head[x];i;i=NEXT[i]){
        int y=ver[i];
        if(y==pre) continue;
        dfs(y,x);
        if(res<=dp[y]-wei[i]){
            if(rres<=dp[y]-wei[i]){
                res=rres;
                rres=dp[y]-wei[i];
            }
            else {
                res=dp[y]-wei[i];
            }
        }
    }
    dp[x]=Max(dp[x],a[x]+rres);
    ans=Max(ans,dp[x]);
    ans=Max(ans,rres+res+a[x]);

}
int main(){
    int u,v;
    long long w;
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<n;i++){
        scanf("%d%d%lld",&u,&v,&w);
        link(u,v,w);
    }
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

E(待补)

猜你喜欢

转载自blog.csdn.net/TelmaZzzz/article/details/84970759