A题
对于这个关系式,xi和yi都是下标,只要记录一下每个下标被加或减的次数,把相加次数最少的分配给最小的值就可以
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 20;
typedef long long ll;
int a[N],b[N],n,m,x,y;
ll ans;

void solve()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n; ++i)
    {
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= m; ++i)
        scanf("%d%d",&x,&y),b[x]++,b[y]--;
    sort(a + 1,a + n + 1);
    sort(b + 1,b + n + 1);
    for(int i = 1;i <= n; ++i)
        ans += 1LL * a[i] * b[n - i + 1];
    printf("%lld\n",ans);
}

int main()
{
    int t = 1;
    //scanf("%d",&t);
    while(t--) solve();
    return 0;
}

B题
可以看出是一个树形DP,f[i][j]表示根为i的子树,子树重量之和为j的最小的l、r之和
很明显重量直接从1-2500会比较慢,所以状态枚举的时候用子树的节点个数对枚举状态进行了缩小
然后暴力更新即可
#include<bits/stdc++.h>
using namespace std;

const int N = 55;
int a[N],lt[N],rt[N],siz[N];
int f[N][N *N],tmp[N * N];
int n,m,u,x,y;

void dfs(int x)
{
    //cout<<x<<endl;
    siz[x] = 1;
    if(lt[x])
    {
        dfs(lt[x]);
        dfs(rt[x]);
        siz[x] += siz[lt[x]] + siz[rt[x]];
        //cout<<siz[x]<<' '<<x<<endl;
        memset(tmp, 0x3f, sizeof(tmp));

        for(int i = siz[lt[x]] * a[1];i <= siz[lt[x]] * a[m]; ++i)
            for(int j = siz[rt[x]] * a[1];j <= siz[rt[x]] * a[m]; ++j)
            {
                int cal = (i + j) / __gcd(i,j);
                tmp[i + j] = min(tmp[i + j],f[lt[x]][i] + f[rt[x]][j] + cal);
                //cout<<i + j<<' '<<tmp[i][j]<<endl;
            }//将他单独计算出来可以有效减少重复的枚举


        for(int i = (siz[x] - 1) * a[m]; i >= (siz[x] - 1) * a[1]; --i)
            for(int j = 1;j <= m; ++j)
                f[x][i + a[j]] = min(f[x][i + a[j]],tmp[i]);  
    } else
        for(int i = 1; i <= m; ++i)  f[x][a[i]] = 0;
}


int main()
{
    scanf("%d%d",&n,&m);
    memset(f,0x3f, sizeof(f));
    for(int i = 1;i <= m; ++i)
        scanf("%d",&a[i]);
    sort(a + 1,a + m + 1);
    while(~scanf("%d%d%d",&u,&x,&y))
    {
        lt[u] = x;
        rt[u] = y;
    }
    dfs(1);
    int ans = 0x3f3f3f3f;
    for(int i = n * a[1];i <= n * a[m]; ++i)
        ans = min(ans,f[1][i]);//cout<<f[1][i]<<' ';
    printf("%d\n",ans);
    return 0;
}