2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

A Radio Prize

大意:

求出一颗树上每个点到其他点的距离的和,两个点之间的距离定义为两个点的权值和乘上路径权值和

思路:

明显是换根DP,不过写的时候写了好久…

将所求拆成两个数:这个点的权值乘路径权值和+目标点的权值乘路径权值和,这样就可以维护了,换根的时候求出父节点到这个节点的贡献即可

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
#define int LL

int n, a[N], sumv[N];
int SUMW = 0;
int sumV[N];
vector<pair<int, int>> mp[N];
int dp[N], dis[N][2], sz[N];
int res[N];
void dfs1(int now, int fa) {
   
    sumv[now] = a[now];
    sz[now] = 1;
    for (int i = 0; i < mp[now].size(); i++) {
   
        int ne = mp[now][i].first, w = mp[now][i].second;
        if (ne == fa) continue;
        dfs1(ne, now);
        sz[now] += sz[ne];                    //子节点数量
        dp[now] += dp[ne] + w * sumv[ne];  //子节点的贡献
        sumv[now] += sumv[ne];                //子节点权值和
        dis[now][0] += dis[ne][0] + w * sz[ne];  //子节点距离和
    }
}

void dfs2(int now, int fa) {
   
    for (int i = 0; i < mp[now].size(); i++) {
   
        int ne = mp[now][i].first, w = mp[now][i].second;
        if (ne == fa) continue;

        dis[ne][1] = dis[now][1] - w * sz[ne] + w * (n - sz[ne]);
        res[ne] = dp[ne] + dis[ne][1] * a[ne] + res[now] -
                  dis[now][1] * a[now] - (dp[ne] + w * sumv[ne]) +
                  w * (SUMW - sumv[ne]);
        dfs2(ne, now);
    }
}

signed main() {
   
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i],SUMW += a[i];
    for (int i = 1; i <= n - 1; i++) {
   
        int x, y, w;
        cin >> x >> y >> w;
        
        mp[x].push_back({
   y, w}), mp[y].push_back({
   x, w});
    }
    dfs1(1, 0);
    res[1] = dp[1] + dis[1][0] * a[1];
    dis[1][1] = dis[1][0];
    dfs2(1, 0);
    for (int i = 1; i <= n; i++) cout << res[i] << endl;
    return 0;
}

B Perfect Flush

大意:

给出n个数,n个数都是由1到k的数组成,现在要从里面找到一个字典序最小的1到k的全排列

思路:

用栈去维护,如果当前栈顶的数字在后面还会出现,且比当前要入栈的数字大,那么就弹栈

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const MAXN = 2e5 + 10;
int n, k;
int a[MAXN];
int pos[MAXN];
stack<int> sta;
int vis[MAXN];
vector<int> ans;
int main() {
   
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
   
        cin >> a[i];
        pos[a[i]] = i;
    }
    for (int i = 1; i <= n; i++) {
   
        if (vis[a[i]])<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值