首页 > 其他分享 >2019-2020 ACM-ICPC Brazil Subregional Programming Contest D Denouncing Mafia

2019-2020 ACM-ICPC Brazil Subregional Programming Contest D Denouncing Mafia

时间:2022-09-18 00:03:46浏览次数:154  
标签:Brazil val Contest int Subregional tr nex now resize

Denouncing Mafia

贪心 + 线段树 + \(dfs\) 序

考虑贪心地每次拿能染色最多的点,每拿走一个点,都会影响其他点的值,如果一个点被染色,则他子树的所有点的贡献值都会 - 1,因此考虑用线段树 + \(dfs\) 序的方式,对树上进行区间修改,每次询问所有点的最大贡献值即可

拿到最大贡献值后,通过那个点网上遍历到根,访问过程中,未被染色的点都要进行一次子树 - 1 的操作

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
#define pii pair<ll, ll>
vector<int>fa, L, R, rnk;
vector<ll>num;
vector<vector<int> >gra;
int tp = 0;

struct node
{
    ll val, lazy;
    int l, r, last;
};
vector<node>tr;

void dfs(int now, int d)
{
    L[now] = ++tp;
    rnk[tp] = now;
    num[tp] = d;
    for(int nex : gra[now])
    {
        if(nex == fa[now]) continue;
        dfs(nex, d + 1);
    }
    R[now] = tp;
}

inline void push_up(int now)
{
    int lson = now << 1, rson = now << 1 | 1;
    int nex = rson;
    if(tr[lson].val > tr[rson].val)
        nex = lson;
    tr[now].val = tr[nex].val;
    tr[now].last = tr[nex].last;
}

void build(int now, int l, int r)
{
    tr[now].val = tr[now].lazy = 0;
    tr[now].l = l;
    tr[now].r = r;
    if(l == r)
    {
        tr[now].val = num[l];
        tr[now].last = l;
        return;
    }
    int mid = l + r >> 1;
    build(now << 1, l, mid);
    build(now << 1 | 1, mid + 1, r);
    push_up(now);
}

void push_down(int now)
{
    if(tr[now].lazy)
    {
        int lson = now << 1, rson = now << 1 | 1;
        tr[lson].lazy += tr[now].lazy;
        tr[rson].lazy += tr[now].lazy;
        tr[lson].val += tr[now].lazy;
        tr[rson].val += tr[now].lazy;
        tr[now].lazy = 0;
    }
}

void update(int now, int L, int R, ll val)
{
    if(L <= tr[now].l && tr[now].r <= R)
    {
        tr[now].lazy += val;
        tr[now].val += val;
        return;
    }
    int mid = tr[now].l + tr[now].r >> 1;
    push_down(now);
    if(L <= mid)
        update(now << 1, L, R, val);
    if(R > mid)
        update(now << 1 | 1, L, R, val);
    push_up(now);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, k;
    cin >> n >> k;
    fa.resize(n + 1);
    L.resize(n + 1);
    R.resize(n + 1);
    rnk.resize(n + 1);
    gra.resize(n + 1);
    tr.resize((n + 1) * 4);
    num.resize(n + 1);
    for(int i=2; i<=n; i++)
    {
        cin >> fa[i];
        gra[fa[i]].push_back(i);
    }
    dfs(1, 1);
    ll ans = 0;
    build(1, 1, n);
    vector<int>vis(n + 1);
    for(int i=0; i<k; i++)
    {
        ll x = tr[1].val, y = tr[1].last;
        if(x == 0) break;
        ans += x;
        y = rnk[y];
        while(y && vis[y] == 0)
        {
            update(1, L[y], R[y], -1);
            vis[y] = 1;
            y = fa[y];
        }
    }
    cout << ans << endl;
    return 0;
}

标签:Brazil,val,Contest,int,Subregional,tr,nex,now,resize
From: https://www.cnblogs.com/dgsvygd/p/16703969.html

相关文章

  • AtCoder Beginner Contest 267 题解
    只会\(A\simG\)主观难度:\(A<B<C<E<D<F<G<Ex\)A-Saturday分别对周一到周五判断即可。#include<bits/stdc++.h>usingnamespacestd;inlineintread(){int......
  • AtCoder Beginner Contest 262(D-E)
    D-IHateNon-integerNumber题意:一个长度为n的数组,选择其中的x项,问其中有多少种选择,这x项的和可以被选择的数目整除,比如,选择3个数,和为6,那么6/3=2,就可以被整除。题解:......
  • Codeforces Round #819 (Div. 1 + Div. 2) and Grimoire of Code Annual Contest 2022
    这场打的稀烂。。。A.MainakandArray题意:将数组中某段子序列翻转一次,求a[n]-a[1]最大的值。思路:有三种情况:第一种,将最小的数翻转到第一位,然后用原来的a[n]减去反......
  • The 2021 China Collegiate Programming Contest (Harbin)
    比赛链接:https://codeforces.com/gym/103447B.MagicalSubsequence题意:给定一个序列\(A\),选择一个长为偶数的子序列\(B\),使得\(B_1+B_2=B_3+B_4...\),问这个......
  • [Editorial] Codeforces Contest 1726
    A.MainakandArray显然如果\([l,r]\)不包括两端那么就不会对答案有影响,那么直接枚举包括两端的情况即可。/*author:Geminidate:September6th,2022url:htt......
  • AtCoder Regular Contest 147
    ProblemA题目大意:由N个正整数组成的序列,我们可以从中取出任意长短序列进行如下操作:序列中(最大值maxn%最小值minn=A),如果A为0则删除maxn,否则用A替换,询问要使得整个序......
  • AtCoder Beginner Contest 265
    E-Warp注意到\(N\)相比\(M\)要小得多。考虑DP,令\(dp_{i,j,k}\)表示一共使用了\(i+j+k\)次操作,且每种操作的使用次数分别为\(i,j,k\)的方案数,然后......
  • AtCoder Beginner Contest 267
    A-Saturday题意:给定今天的日期,问到周六还有几天。分析:暴力判断即可。代码:intmain(){ cin>>s; if(s=="Monday")ans=5; if(s=="Tuesday")ans=4; if(s=="We......
  • AtCoder Beginner Contest 267
    https://atcoder.jp/contests/abc267全部的AC代码:https://atcoder.jp/contests/abc267/submissions/me?f.Task=&f.LanguageName=&f.Status=AC&f.User=HinanawiTenshiE......
  • codeforces.ml/contest/519/problem/E 求树上到任意两个点距离相等的点 树上倍增 分类
    E.AandBandLectureRoomstimelimitpertest2secondsmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputAandBarep......