Niestety, nie byliśmy w stanie w pełni poprawnie wyświetlić tego pliku, ponieważ nie jest zakodowany w UTF-8.
Możesz pobrać ten plik i spróbować otworzyć go samodzielnie.
// Lupus Nocawy 17 V 2014, PA2014 // http://potyczki.mimuw.edu.pl/ // Runda 5 // Zadanie: FIO // Fiolki [B] #include <cstdio> #include <iostream> #include <cassert> #include <cstring> #include <algorithm> #include <vector> #include <deque> #include <queue> #include <stack> #include <list> #include <set> #include <map> #include <cmath> using namespace std; #define REP(i,n) for(int i=0, _n=n; i<_n; ++i) #define FOR(i,a,b) for(int i=(a), _b=(b); i<=_b; ++i) #define FORD(i,a,b) for(int i=(a), _b=(b); i>=_b; --i) #define IT(i,x) __typeof__(x) i=x #define FOREACH(it,x) for(__typeof__((x).begin()) it=(x).begin(); it!=(x).end(); ++it) #define ALL(x) x.begin(),x.end() #define MP make_pair #define PB push_back #define DEBUG(x) if(debug) cout << x << endl; typedef long long int lli; typedef unsigned long long int llu; typedef pair<int,int> pii; const int debug=0; const int INF = 2147483647; const int max_n = 200000; const int max_m = 200000; const int max_k = 500000; class reaction{ public: int a,b; // reagents int dist; // distance between reagents in the final vial int prio; // the original priority of this reaction reaction(int a,int b,int dist,int prio): a(a), b(b), dist(dist), prio(prio) {} }; bool operator< (const reaction &X, const reaction &Y){ return X.dist < Y.dist; } bool reaction_greater (const reaction &X, const reaction &Y){ return X.dist > Y.dist; } //bool reaction_prio (const reaction &X, const reaction &Y){ // return X.prio < Y.prio; //} class reaction_prio{ public: bool operator() (const reaction &X, const reaction &Y){ return X.prio > Y.prio; } }; int main(void){ int n,m,k; scanf("%d %d %d ", &n, &m, &k); vector<int> g(n); REP(i,n){ scanf("%d ", &g[i]); } //REP(i,n){printf("%d ", g[i]);} printf("\n"); vector<pii> seq(m); REP(i,m){ int a,b; scanf("%d %d ", &a, &b); seq[i] = MP(a-1, b-1); } vector<pii> react(k); REP(i,k){ int c,d; scanf("%d %d ", &c, &d); react[i] = MP(c-1,d-1); } vector<int> id_final(n); // the vial number in which element ends vector<int> pos_final(n); // position in final vial vector<list<int> > L(n); REP(i,n){ // construct empty vials L[i].PB(i); } REP(i,m){ // simulate merging vials int a = seq[i].first; int b = seq[i].second; //printf("%d %d\n", a,b); L[b].splice(L[b].begin(),L[a]); } REP(i,n){ // calculate position in final vial //printf("%d: ", i); if(!L[i].empty()){ int j=0; FOREACH(it,L[i]){ id_final[*it] = i; pos_final[*it] = j++; //printf("%d ",*it); } } //printf("\n"); } vector<vector<reaction> > Rv(n); vector<list<reaction> > R(n); REP(i,k){ int a = react[i].first; int b = react[i].second; if(id_final[a]==id_final[b]){ // elements ever meet if(pos_final[a]>pos_final[b]) swap(a,b); Rv[a].PB( reaction(a, b, pos_final[b]-pos_final[a], i) ); } } REP(i,n){ sort(ALL(Rv[i]), reaction_greater); } REP(i,n){ FOREACH(it,Rv[i]){ R[i].PB(*it); } } lli result=0; REP(i,n){ // construct empty vials L[i].clear(); L[i].PB(i); } priority_queue<reaction, vector<reaction>, reaction_prio> prioR; REP(i,m){ // simulate merging vials int a = seq[i].first; int b = seq[i].second; int size_a = L[a].size(); int size_b = L[b].size(); L[b].splice(L[b].begin(),L[a]); while(!R[a].empty() && R[a].back().dist < size_a + size_b){ prioR.push(R[a].back()); R[a].pop_back(); } while(!prioR.empty()){ int x = prioR.top().a; int y = prioR.top().b; prioR.pop(); int s = min(g[x],g[y]); g[x]-=s; g[y]-=s; result += 2*s; } FOREACH(it,R[b]){ it->dist += size_a; } //R[b].merge(R[a]); R[b].merge(R[a], reaction_greater); } printf("%lld\n", result); return 0; } /* Niekoniecznie wszystkie substancje zostan� przelane do jednej fiolki, wi�c mo�e pozosta� kilka fiolek. 1. Potrzebujemy ustali� kolejno�� substancji we fiolkach na ko�cu. Naj�atwiej chyba budowa� fiolki wg przepisu za pomoc� list, i na ko�cu przelecie� listy i obliczy� dla ka�dej substancji pozycj� na li�cie. Przyjmijmy, �e przelewany bez odwracania - czyli zlewaj�c jedn� fiolk� do drugiej, to co by�o na g�rze pierwszej fiolki nadal jest na g�rze. 2. Pary reakcji maj� ju� na wej�ciu ustalon� kolejno��. �eby szybko ich u�ywa�, zapiszmy ka�d� reakcj� na li�cie dowi�zanej do jednego z element�w kt�rego dotyczy. - je�eli dwa elementy nigdy si� nie spotkaj�, to tak� reakcj� oczywi�cie pomijamy - wpp, przypisujemy reakcj� do tego elementu, kt�ry jest w wynikowej fiolce WY�EJ i jednocze�nie zapisujemy jaka jest odleg�o�� mi�dzy elementami w tej fiolce - b�dzie to potrzebne do obliczenia, w kt�rym momencie reakcja mo�e zosta� u�yta. 3. Ka�da substancja ma teraz swoj� list� reakcji. Sortujemy ka�d� list� wg odleg�o�ci do drugiego reagenta, rosn�co. 4. Teraz symulujemy zlewanie od pocz�tku. - A) Kiedy zlewamy jedn� fiolk� do drugiej, to bierzemy list� reakcji ze szczytu pierwszej fiolki i �ci�gamy z jej pocz�tku te reakcje, kt�re musimy wykona�. Poniewa� przypisywali�my reakcje do tego elementu z pary, kt�ry jest wy�ej, to wiadomo �e wszystkie reakcje kt�re musimy wykona� s� w�a�nie na szczycie pierwszej fiolki. Aby to zrobi�, po prostu patrzymy jak� d�ugo�� ma druga fiolka, i �ci�gamy z pocz�tku listy dop�ki odleg�o�ci s� mniejsze (tak mamy posortowane reakcje). �ci�gni�te reakcje wk�adamy do priority_queue gdzie kluczem jest ich oryginalny priorytet i w ko�cu wykonujemy. - B) Nast�pnie bierzemy list� reakcji ze szczytu drugiej fiolki i scalamy z tym co pozosta�o na li�cie pierwszej fiolki (scalanie posortowanych list). Przed scaleniem musimy oczywi�cie poprawi� odleg�o�ci na li�cie z drugiej fiolki, bo przesuwamy jej punk odniesienia. Zauwa�my, �e po zlaniu mamy zawsze jedn� list� przypisan� do jednej fiolki. Z�o�ono�� - chyba O(k + m*lgk + k*lgk + m*k), niestety scalanie posortowanych list moze wyjsc kwadratowe ;/ */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | // Lupus Nocawy 17 V 2014, PA2014 // http://potyczki.mimuw.edu.pl/ // Runda 5 // Zadanie: FIO // Fiolki [B] #include <cstdio> #include <iostream> #include <cassert> #include <cstring> #include <algorithm> #include <vector> #include <deque> #include <queue> #include <stack> #include <list> #include <set> #include <map> #include <cmath> using namespace std; #define REP(i,n) for(int i=0, _n=n; i<_n; ++i) #define FOR(i,a,b) for(int i=(a), _b=(b); i<=_b; ++i) #define FORD(i,a,b) for(int i=(a), _b=(b); i>=_b; --i) #define IT(i,x) __typeof__(x) i=x #define FOREACH(it,x) for(__typeof__((x).begin()) it=(x).begin(); it!=(x).end(); ++it) #define ALL(x) x.begin(),x.end() #define MP make_pair #define PB push_back #define DEBUG(x) if(debug) cout << x << endl; typedef long long int lli; typedef unsigned long long int llu; typedef pair<int,int> pii; const int debug=0; const int INF = 2147483647; const int max_n = 200000; const int max_m = 200000; const int max_k = 500000; class reaction{ public: int a,b; // reagents int dist; // distance between reagents in the final vial int prio; // the original priority of this reaction reaction(int a,int b,int dist,int prio): a(a), b(b), dist(dist), prio(prio) {} }; bool operator< (const reaction &X, const reaction &Y){ return X.dist < Y.dist; } bool reaction_greater (const reaction &X, const reaction &Y){ return X.dist > Y.dist; } //bool reaction_prio (const reaction &X, const reaction &Y){ // return X.prio < Y.prio; //} class reaction_prio{ public: bool operator() (const reaction &X, const reaction &Y){ return X.prio > Y.prio; } }; int main(void){ int n,m,k; scanf("%d %d %d ", &n, &m, &k); vector<int> g(n); REP(i,n){ scanf("%d ", &g[i]); } //REP(i,n){printf("%d ", g[i]);} printf("\n"); vector<pii> seq(m); REP(i,m){ int a,b; scanf("%d %d ", &a, &b); seq[i] = MP(a-1, b-1); } vector<pii> react(k); REP(i,k){ int c,d; scanf("%d %d ", &c, &d); react[i] = MP(c-1,d-1); } vector<int> id_final(n); // the vial number in which element ends vector<int> pos_final(n); // position in final vial vector<list<int> > L(n); REP(i,n){ // construct empty vials L[i].PB(i); } REP(i,m){ // simulate merging vials int a = seq[i].first; int b = seq[i].second; //printf("%d %d\n", a,b); L[b].splice(L[b].begin(),L[a]); } REP(i,n){ // calculate position in final vial //printf("%d: ", i); if(!L[i].empty()){ int j=0; FOREACH(it,L[i]){ id_final[*it] = i; pos_final[*it] = j++; //printf("%d ",*it); } } //printf("\n"); } vector<vector<reaction> > Rv(n); vector<list<reaction> > R(n); REP(i,k){ int a = react[i].first; int b = react[i].second; if(id_final[a]==id_final[b]){ // elements ever meet if(pos_final[a]>pos_final[b]) swap(a,b); Rv[a].PB( reaction(a, b, pos_final[b]-pos_final[a], i) ); } } REP(i,n){ sort(ALL(Rv[i]), reaction_greater); } REP(i,n){ FOREACH(it,Rv[i]){ R[i].PB(*it); } } lli result=0; REP(i,n){ // construct empty vials L[i].clear(); L[i].PB(i); } priority_queue<reaction, vector<reaction>, reaction_prio> prioR; REP(i,m){ // simulate merging vials int a = seq[i].first; int b = seq[i].second; int size_a = L[a].size(); int size_b = L[b].size(); L[b].splice(L[b].begin(),L[a]); while(!R[a].empty() && R[a].back().dist < size_a + size_b){ prioR.push(R[a].back()); R[a].pop_back(); } while(!prioR.empty()){ int x = prioR.top().a; int y = prioR.top().b; prioR.pop(); int s = min(g[x],g[y]); g[x]-=s; g[y]-=s; result += 2*s; } FOREACH(it,R[b]){ it->dist += size_a; } //R[b].merge(R[a]); R[b].merge(R[a], reaction_greater); } printf("%lld\n", result); return 0; } /* Niekoniecznie wszystkie substancje zostan� przelane do jednej fiolki, wi�c mo�e pozosta� kilka fiolek. 1. Potrzebujemy ustali� kolejno�� substancji we fiolkach na ko�cu. Naj�atwiej chyba budowa� fiolki wg przepisu za pomoc� list, i na ko�cu przelecie� listy i obliczy� dla ka�dej substancji pozycj� na li�cie. Przyjmijmy, �e przelewany bez odwracania - czyli zlewaj�c jedn� fiolk� do drugiej, to co by�o na g�rze pierwszej fiolki nadal jest na g�rze. 2. Pary reakcji maj� ju� na wej�ciu ustalon� kolejno��. �eby szybko ich u�ywa�, zapiszmy ka�d� reakcj� na li�cie dowi�zanej do jednego z element�w kt�rego dotyczy. - je�eli dwa elementy nigdy si� nie spotkaj�, to tak� reakcj� oczywi�cie pomijamy - wpp, przypisujemy reakcj� do tego elementu, kt�ry jest w wynikowej fiolce WY�EJ i jednocze�nie zapisujemy jaka jest odleg�o�� mi�dzy elementami w tej fiolce - b�dzie to potrzebne do obliczenia, w kt�rym momencie reakcja mo�e zosta� u�yta. 3. Ka�da substancja ma teraz swoj� list� reakcji. Sortujemy ka�d� list� wg odleg�o�ci do drugiego reagenta, rosn�co. 4. Teraz symulujemy zlewanie od pocz�tku. - A) Kiedy zlewamy jedn� fiolk� do drugiej, to bierzemy list� reakcji ze szczytu pierwszej fiolki i �ci�gamy z jej pocz�tku te reakcje, kt�re musimy wykona�. Poniewa� przypisywali�my reakcje do tego elementu z pary, kt�ry jest wy�ej, to wiadomo �e wszystkie reakcje kt�re musimy wykona� s� w�a�nie na szczycie pierwszej fiolki. Aby to zrobi�, po prostu patrzymy jak� d�ugo�� ma druga fiolka, i �ci�gamy z pocz�tku listy dop�ki odleg�o�ci s� mniejsze (tak mamy posortowane reakcje). �ci�gni�te reakcje wk�adamy do priority_queue gdzie kluczem jest ich oryginalny priorytet i w ko�cu wykonujemy. - B) Nast�pnie bierzemy list� reakcji ze szczytu drugiej fiolki i scalamy z tym co pozosta�o na li�cie pierwszej fiolki (scalanie posortowanych list). Przed scaleniem musimy oczywi�cie poprawi� odleg�o�ci na li�cie z drugiej fiolki, bo przesuwamy jej punk odniesienia. Zauwa�my, �e po zlaniu mamy zawsze jedn� list� przypisan� do jednej fiolki. Z�o�ono�� - chyba O(k + m*lgk + k*lgk + m*k), niestety scalanie posortowanych list moze wyjsc kwadratowe ;/ */ |