제출 #1332551

#제출 시각아이디문제언어결과실행 시간메모리
1332551radaiosm7Jobs (BOI24_jobs)C++20
69 / 100
552 ms102648 KiB
//chockolateman

#include<bits/stdc++.h>

using namespace std;

const long long INF = 1000000000000000LL;

long long N,a[300005],par[300005],p[300005],s[300005],lead[300005],dp[300005],tin[300005],tout[300005],timer,rev_tin[300005];
long long S,d[300005],prof[300005],ans;
bool used[300005],active[300005];
vector<long long> adj[300005],active_edge[300005];
stack<long long> to_buy;

void dfs1(long long v)
{
    tin[v] = ++timer;
    rev_tin[timer] = v;
    prof[v] = prof[par[v]] + a[v];
    d[v] = min(d[par[v]],prof[v]);
    if(par[v]==0)
        d[v] = prof[v];
    for(auto u : adj[v])
    {
        if(u != par[v])
            dfs1(u);
    }
    tout[v] = timer;
}

struct Node
{
    long long maxim,pos,lazy = 0;
}st[1200005];

Node combine(Node left,Node right)
{
    Node ret;
    if(left.maxim >= right.maxim)
    {
        ret.maxim = left.maxim;
        ret.pos = left.pos;
    }
    else
    {
        ret.maxim = right.maxim;
        ret.pos = right.pos;
    }
    return ret;
}

void build(long long v = 1,long long start = 1,long long end = N)
{
    if(start==end)
    {
        st[v].maxim = d[rev_tin[start]];
        st[v].pos = rev_tin[start];
        st[v].lazy = 0;
        return;
    }
    long long mid = (start + end)/2;
    build(2*v,start,mid);
    build(2*v+1,mid+1,end);
    st[v] = combine(st[2*v],st[2*v+1]);
}

void propagate(long long v,long long start,long long end);

void update(long long l,long long r,long long val,long long v = 1,long long start = 1,long long end = N)
{
    if(start==l && end==r)
    {
        st[v].maxim += val;
        st[v].lazy += val;
        return;
    }
    propagate(v,start,end);
    long long mid = (start + end)/2;
    if(r <= mid)
        update(l,r,val,2*v,start,mid);
    else if(l > mid)
        update(l,r,val,2*v+1,mid+1,end);
    else
    {
        update(l,mid,val,2*v,start,mid);
        update(mid+1,r,val,2*v+1,mid+1,end);
    }
    st[v] = combine(st[2*v],st[2*v+1]);
}

void propagate(long long v,long long start,long long end)
{
    if(st[v].lazy)
    {
        long long mid = (start + end)/2;
        update(start,mid,st[v].lazy,2*v,start,mid);
        update(mid+1,end,st[v].lazy,2*v+1,mid+1,end);
        st[v].lazy = 0;
    }
}

void activate(long long pos,long long v = 1,long long start = 1,long long end = N)
{
    if(start==end)
    {
        st[v].maxim = -INF;
        st[v].pos = 0;
        return;
    }
    propagate(v,start,end);
    long long mid = (start + end)/2;
    if(pos <= mid)
        activate(pos,2*v,start,mid);
    else
        activate(pos,2*v+1,mid+1,end);
    st[v] = combine(st[2*v],st[2*v+1]);
}

long long find_Sett(long long i)
{
    if(p[i]==i)
        return i;
    p[i] = find_Sett(p[i]);
    return p[i];
}

bool is_Same_Sett(long long i,long long j)
{
    return find_Sett(i) == find_Sett(j);
}

long long dp_Sett(long long i)
{
    return dp[find_Sett(i)];
}

void union_Sett(long long i,long long j)
{
    if(is_Same_Sett(i,j))
        return;
    long long x = find_Sett(i);
    long long y = find_Sett(j);
    if(s[x] < s[y])
        swap(x,y);
    p[y] = x;
    s[x] += s[y];
    dp[x] += dp[y];
    lead[x] = min(lead[x],lead[y]);
}

void open(long long v)
{
    activate(tin[v]);
    active[v] = true;
    dp[v] = a[v];
    s[v] = 1;
    p[v] = v;
    lead[v] = v;
    for(auto u : adj[v])
        if(u != par[v] && active[u] && dp_Sett(u) > 0)
        {
            active_edge[v].push_back(u);
            active_edge[u].push_back(v);
            union_Sett(v,u);
        }
    while(dp_Sett(v) > 0)
    {
        long long x = find_Sett(v);
        if(used[par[lead[x]]])
        {
            to_buy.push(lead[x]);
            break;
        }
        if(active[par[lead[x]]])
        {
            active_edge[par[lead[x]]].push_back(lead[x]);
            active_edge[lead[x]].push_back(par[lead[x]]);
            union_Sett(x,par[lead[x]]);
        }
        else
            break;
    }
}

void dfs2(long long v) //buy
{
    S += a[v];
    ans += a[v];
    update(tin[v],tout[v],-a[v]);
    used[v] = true;
    for(auto u : active_edge[v])
        if(u != par[v])
            dfs2(u);
}

int main()
{
    scanf("%lld%lld",&N,&S);
    for(long long i = 1 ; i <= N ; i++)
    {
        scanf("%lld%lld",&a[i],&par[i]);
        if(par[i] != 0)
        {
            adj[i].push_back(par[i]);
            adj[par[i]].push_back(i);
        }
    }
    for(long long i = 1 ; i <= N ; i++)
        if(par[i]==0)
        {
            dfs1(i);
        }
    used[0] = true;
    build();
    bool moved = true;
    while(moved)
    {
        moved = false;
        while(st[1].pos > 0 && st[1].maxim + S >= 0)
        {
            moved = true;
            open(st[1].pos);
        }
        if(!to_buy.empty())
        {
            moved = true;
            long long v = to_buy.top();
            to_buy.pop();
            if(!used[v])
                dfs2(v);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:198:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  198 |     scanf("%lld%lld",&N,&S);
      |     ~~~~~^~~~~~~~~~~~~~~~~~
Main.cpp:201:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  201 |         scanf("%lld%lld",&a[i],&par[i]);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...