E.Partial Sum

题意:

给出一个a序列,a1 a2 ... an,最多可以选择m个区间[L,R],更新 区间和 - C,并且选过的[L,R]不能再被选择,问你最后的最大值

题解:

不用想那么复杂,直接前缀和排序,最大的减去最小的再减去C>=0,更新答案,否则跳出

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100005;
ll pre[maxn],a[maxn];
int main()
{
    int n,m,c;
    while(~scanf("%d%d%d",&n,&m,&c))
    {
        pre[0] = 1ll*0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            pre[i] = pre[i-1] + a[i];
        }
        sort(pre,pre+1+n);
        ll ans = 0,l = 0,r = n,cnt = 0;
        while(cnt < m && pre[r]-pre[l]-c >=0){
            ans += (pre[r] - pre[l] - c);
            cnt++,r--,l++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

H.Highway

题意:

给出一颗树,有n个点和n-1条边,问你将这个树重新拆分成一颗边权最大的树,树的边权和是多少,每俩个点之间的距离是之前给出的树的距离

题解:

我们可以自己手画一下,先找出树的直径,直径对应俩个点,那么另外n-2个点的最大的边权肯定是连着树的直径对应的俩个点

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100005;
vector< pair<int,ll> > v[maxn];
int flag[maxn];
int pos,n;
ll a[maxn],b[maxn],maxx = 0;
void init()
{
    for(int i=1;i<=n;i++){
        v[i].clear();
        flag[i] = 0;
        a[i] = 1ll*0;
        b[i] = 1ll*0;
    }
}
void dfs1(int x,ll len)
{
    a[x] = len;
    if(a[x] > maxx){
        maxx = a[x],pos = x;
    }
    for(int i=0;i<v[x].size();i++){
        if(!flag[v[x][i].first]){
            flag[v[x][i].first] = 1;
            dfs1(v[x][i].first , len + 1ll*v[x][i].second);
        }
    }
}
void dfs2(int x,ll len)
{
    a[x] = max(a[x],len);
    for(int i=0;i<v[x].size();i++){
        if(!flag[v[x][i].first]){
            flag[v[x][i].first] = 1;
            dfs1(v[x][i].first , len + 1ll*v[x][i].second);
        }
    }
}
void dfs3(int x,ll len)
{
    a[x] = len;
    for(int i=0;i<v[x].size();i++){
        if(!flag[v[x][i].first]){
            flag[v[x][i].first] = 1;
            dfs1(v[x][i].first , len + 1ll*v[x][i].second);
        }
    }
}
int main()
{
    ll x,y,l,ans;
    while(~scanf("%d",&n))
    {
        init();
        for(int i=1;i<n;i++){
            scanf("%d%d%lld",&x,&y,&l);
            v[x].push_back(make_pair(y,l));
            v[y].push_back(make_pair(x,l));
        }
        int now1,now2;
        maxx = 0,dfs1(1,0);
        memset(flag,0,sizeof(flag));
        now1 = pos,maxx = 0,dfs1(pos,0);
        now2 = pos;
        ll ans = maxx;
        //cout<<now1<<" "<<now2<<" "<<ans<<endl;
        memset(flag,0,sizeof(flag));
        dfs3(now1,0);
        for(int i=1;i<=n;i++){
            b[i] = a[i];
        }
        memset(flag,0,sizeof(flag));
        dfs2(now2,0);
        for(int i=1;i<=n;i++)
        {
            if(i == now1 || i == now2)
                continue ;
            ans += max(a[i],b[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

I:Strange Optimization

题意:

题目说的那么多,就是让你求2×n×m/gcd(n,m)

题解:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    ll n , m;
    while(~scanf("%lld%lld",&n,&m))
    {
        ll gc = __gcd(n,m);
        printf("1/%lld\n",n*m*2/gc);
    }
    return 0;
}