Submission #97639

#TimeUsernameProblemLanguageResultExecution timeMemory
97639JedrzejOlkowskiTransport (COCI19_transport)C++14
130 / 130
820 ms19996 KiB
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct trio{ ll suma, mindo; int v; }; trio make_trio(ll a, ll b, int c){ trio wyn; wyn.suma=a; wyn.mindo=b; wyn.v=c; return wyn; } const int N=1e5+50; const ll I=1000LL*1000LL*1000LL*1000LL*1000LL*1000LL; vector< pair<int, int> >Kra[N]; int Paliwo[N]; int Rozmiar[N]; int Ojciec[N]; int Odw[N]; int Zaz[N]; int Wynik[N]; vector< trio >Start[N]; vector<ll>Odleglosci; void WczytajDane(int &n){ cin>>n; int a, b, c; for(int i=1; i<=n; ++i) cin>>Paliwo[i]; for(int i=1; i<n; i++){ cin>>a>>b>>c; Kra[a].push_back( make_pair(b, c) ); Kra[b].push_back( make_pair(a, c) ); } } void LiczRozmiar(int v){ Odw[v]=1; Rozmiar[v]++; for(int i=0; i<(int)Kra[v].size(); i++){ if( Odw[ Kra[v][i].first ]==1 ) continue; LiczRozmiar(Kra[v][i].first); Ojciec[ Kra[v][i].first ]=v; Rozmiar[v]+=Rozmiar[Kra[v][i].first]; } } int LiczCentroid(vector<int> &Aktu){ int v, czy, s; s=(int)Aktu.size(); for(int i=0; i<(int)Aktu.size(); i++){ v=Aktu[i]; czy=1; for(int j=0; j<(int)Kra[v].size(); j++){ if( Ojciec[ v ]==Kra[v][j].first ) continue; if( Rozmiar[ Kra[v][j].first ]>s/2 ) czy=0; } if( s-Rozmiar[v]>s/2 ) czy=0; if( czy==1 ) return v; } return 0; } bool Porownaj(trio a, trio b){ if(a.mindo<b.mindo) return 1; return 0; } int PierwszyWiekszy(ll szukana){ int p, k, s; p=0; k=(int)Odleglosci.size()-1; while(p<k){ s=(p+k)/2; if(Odleglosci[s]>=szukana) k=s; else p=s+1; } if(Odleglosci[p]<szukana) return 0; return (int)Odleglosci.size()-p; } int Odejmowanie(ll szukana, int gdzie){ int p, k, s; p=0; k=(int)Start[gdzie].size()-1; while(p<k){ s=(p+k)/2; if(Start[gdzie][s].mindo>=szukana) k=s; else p=s+1; } if(Start[gdzie][p].mindo<szukana) return 0; return (int)Start[gdzie].size()-p; } void LiczWyniki(int aktu){ //cout << "LICZE " << Kra[2][aktu].first << endl; for(int i=0; i<(int)Start[aktu].size(); i++){ if( Start[aktu][i].v==-1 ) continue; // cout << "licze " << Start[aktu][i].v << " " << Start[aktu][i].suma << endl; // cout << "ile wiekszych " << PierwszyWiekszy(-Start[aktu][i].suma) << endl; // cout << "ile odejmuje " << Odejmowanie(-Start[aktu][i].mindo, aktu) << endl; // if( Start[aktu][i].v==5 ) cout << "dodaej " << (PierwszyWiekszy(-Start[aktu][i].suma)-Odejmowanie(-Start[aktu][i].suma, aktu)+1) << endl; Wynik[ Start[aktu][i].v ]+=(PierwszyWiekszy(-Start[aktu][i].suma)-Odejmowanie(-Start[aktu][i].suma, aktu)+1); } } void LiczAktu(int v, vector<int> &Dod){ Odw[v]=1; Dod.push_back(v); for(int i=0; i<(int)Kra[v].size(); i++){ if(Odw[ Kra[v][i].first ]==0) LiczAktu(Kra[v][i].first, Dod); } } void LiczWynikWrzucOdleglosci(int v, int gdzie_wyn, ll suma, ll mini_do, ll mini_od, int k){ // cout << "v " << v << endl; // cout << "mini_do " << mini_do << endl; // cout << "roznica " << (ll)Paliwo[v] << endl; // cout << "lacznie " << mini_do+(ll)Paliwo[v] << endl; if(mini_do>=0LL){ Wynik[gdzie_wyn]++; // if(gdzie_wyn==5) cout << "dodaje " << v << endl; } //cout << "mini_do " << v << " : " << mini_do << endl; //if( gdzie_wyn==5 ) cout << "dodaje do 5 " << v << " : " << mini_do << endl; Odleglosci.push_back( mini_do ); Odw[v]=1; ll mini, mini2; // cout << v << ": " << mini_od << endl; if(mini_od<0LL) Start[k].push_back( make_trio( suma-(ll)Paliwo[gdzie_wyn]+(ll)Paliwo[v], mini_do, -1 ) ); else Start[k].push_back( make_trio( suma-(ll)Paliwo[gdzie_wyn]+(ll)Paliwo[v], mini_do, v ) ); //cout << "vS " << v << " " << mini_do << endl; for(int i=0; i<(int)Kra[v].size(); i++){ if( Odw[ Kra[v][i].first ]==1 ) continue; mini=min(mini_do, suma+(ll)Paliwo[v]-(ll)Kra[v][i].second); mini2=min(-(ll)Kra[v][i].second+(ll)Paliwo[Kra[v][i].first], mini_od-(ll)Kra[v][i].second+(ll)Paliwo[Kra[v][i].first]); LiczWynikWrzucOdleglosci(Kra[v][i].first, gdzie_wyn, suma+(ll)Paliwo[v]-(ll)Kra[v][i].second, mini, mini2, k); } } void LiczCentroid(int v){ vector<int>Aktu; LiczAktu(v, Aktu); if( (int)Aktu.size()==1 ) return; for(int i=0; i<(int)Aktu.size(); i++) Odw[Aktu[i]]=Zaz[Aktu[i]]; LiczRozmiar(Aktu[0]); int c=LiczCentroid(Aktu); Zaz[c]=1; for(int i=0; i<(int)Aktu.size(); i++){ Ojciec[Aktu[i]]=Rozmiar[ Aktu[i] ]=0; Odw[Aktu[i]]=Zaz[Aktu[i]]; } //cout << endl; // cout << "CENTROID " << c << endl; for(int i=0; i<(int)Kra[c].size(); i++){ if( Zaz[ Kra[c][i].first ]==1 ) continue; LiczWynikWrzucOdleglosci(Kra[c][i].first, c, (ll)Paliwo[c]-(ll)Kra[c][i].second, (ll)Paliwo[c]-(ll)Kra[c][i].second, -(ll)Kra[c][i].second+(ll)Paliwo[ Kra[c][i].first ], i); sort( Start[i].begin(), Start[i].end(), Porownaj ); } for(int i=0; i<(int)Aktu.size(); i++) Odw[Aktu[i]]=Zaz[Aktu[i]]; // cout << "ODLEGLOSCI " << endl; sort(Odleglosci.begin(), Odleglosci.end()); // for(int i=0; i<(int)Odleglosci.size(); i++) cout << Odleglosci[i] << " "; // cout << endl; for(int i=0; i<(int)Kra[c].size(); i++){ if( Zaz[ Kra[c][i].first ]==1 ) continue; // cout << "START KORZEEN " << Kra[c][i].first << endl; // for(int j=0; j<(int)Start[i].size(); j++) cout << Start[i][j].suma << " " << Start[i][j].mindo << " " << Start[i][j].v << endl; } //cout << "licze " << c << endl; for(int i=0; i<(int)Kra[c].size(); i++){ if( Zaz[ Kra[c][i].first ]==0 ) LiczWyniki(i); Start[i].clear(); } Odleglosci.clear(); for(int i=0; i<(int)Kra[c].size(); i++){ if( Zaz[ Kra[c][i].first ]==0 ) LiczCentroid( Kra[c][i].first ); } } int main (){ int n; ll suma=0LL; WczytajDane(n); LiczCentroid(1); //for(int i=1; i<=n; i++) cout << i << " : " << Paliwo[i] << endl; //for(int i=1; i<=n; i++) cout << i << ": " << Wynik[i] << endl; for(int i=1; i<=n; i++) suma+=(ll)Wynik[i]; cout<<suma<<"\n"; return 0; }
#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...
#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...