제출 #1332328

#제출 시각아이디문제언어결과실행 시간메모리
1332328KALARRYJobs (BOI24_jobs)C++20
29 / 100
456 ms103744 KiB
//chockolateman

#include<bits/stdc++.h>

using namespace std;

const long long INF = 1000000000000000000ll;

long long N,a[300005],par[300005],prof[300005],d[300005],tin[300005],tout[300005],timer,rev_tin[300005];
long long S,ans;
bool used[300005];
vector<long long> adj[300005];

struct Node
{
    long long unactive,pos1,active,pos2,prof,lazy = 0; //ret.unactive = needed to pass, ret.active = max_active score
}st[1200005];

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

Node combine(Node left,Node right)
{
    Node ret;
    if(left.pos1==0)
    {
        ret.unactive = right.unactive;
        ret.pos1 = right.pos1;
    }
    else if(right.pos1==0)
    {
        ret.unactive = left.unactive;
        ret.pos1 = left.pos1;
    }
    else if(left.unactive >= right.unactive)
    {
        ret.unactive = left.unactive;
        ret.pos1 = left.pos1;
    }
    else
    {
        ret.unactive = right.unactive;
        ret.pos1 = right.pos1;
    }

    if(left.pos2==0)
    {
        ret.active = right.active;
        ret.pos2 = right.pos2;
    }
    else if(right.pos2==0)
    {
        ret.active = left.active;
        ret.pos2 = left.pos2;
    }
    else if(left.active >= right.active)
    {
        ret.active = left.active;
        ret.pos2 = left.pos2;
    }
    else
    {
        ret.active = right.active;
        ret.pos2 = right.pos2;
    }

    return ret;
}

void build(long long v = 1,long long start = 1,long long end = N)
{
    if(start==end)
    {
        if(d[start] + S >= 0)
        {
            st[v].unactive = - INF;
            st[v].pos1 = 0;
            st[v].active = prof[start];
            st[v].pos2 = start;
            st[v].prof = prof[start];
            st[v].lazy = 0;
        }
        else
        {
            st[v].unactive = d[start];
            st[v].pos1 = start;
            st[v].active = -INF;
            st[v].pos2 = 0;
            st[v].prof = prof[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].unactive += val;
        st[v].active += val;
        st[v].prof += 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 active(long long pos,long long v = 1,long long start = 1,long long end = N)
{
    if(start==end)
    {
        st[v].unactive = - INF;
        st[v].pos1 = 0;
        st[v].active = st[v].prof;
        st[v].pos2 = start;
        return;
    }
    propagate(v,start,end);
    long long mid = (start + end)/2;
    if(pos <= mid)
        active(pos,2*v,start,mid);
    else
        active(pos,2*v+1,mid+1,end);
    st[v] = combine(st[2*v],st[2*v+1]);
}

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

void use(long long v)
{
    if(used[v])
        return;
    used[v] = true;
    S += a[v];
    ans += a[v];
    deactive(tin[v]);
    update(tin[v],tout[v],-a[v]);
    use(par[v]);
}

int main()
{
    scanf("%lld%lld",&N,&S);
    for(long long p,i = 1 ; i <= N ; i++)
    {
        scanf("%lld%lld",&a[i],&p);
        par[i] = p;
        if(p==0)
            par[i] = i;
        else
        {
            adj[p].push_back(i);
            adj[i].push_back(p);
        }
    }
    for(long long i = 1 ; i <= N ; i++)
        if(par[i]==i)
            dfs(i,i);
    build();
    bool moved = true;
    while(moved)
    {
        moved = false;
        while(st[1].pos2 > 0 && st[1].active >= 0)
        {
            moved = true;
            use(rev_tin[st[1].pos2]);
        }
        while(st[1].pos1 > 0 && st[1].unactive + S >= 0)
        {
            moved = true;
            active(st[1].pos1);
        }
    }
    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],&p);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~
#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...