#include #define ll long long using namespace std; ll n, m, V, LIMIT, mind, USED = 2, DIVIDER, MaxBadnum, MaxBadvert, Vleft; unsigned ll SUM = 0; ll e; ll SECTIONS; const long double LUFT100 = 1.2; ll MEDJUparts = 50; ll MEDJUdiv; const bool test = 0; //130 best //tried: 100 (25.389), 200 (22.088), 150 (27.707), 160 (25.497), 130(27.793), 120 (26.819), 140 (26.657), 125 (27.119), 127 (27.477), 129(27.117), 128 (27.159), 131 (27.157) struct soldiers { ll x; ll y; ll num; }good[50096], bad[50096], cur; struct commands { ll xa; ll ya; ll xb; ll yb; ll amount; }; vector < vector > M(1000); vector COM; vector GOOD; vector BAD; vector < vector > MEDJU(1000); //vector ALIVE; bool compTORIGHT(soldiers i1, soldiers i2) { if(abs(i1.x - i2.x) <= 50000 && abs(i1.num - i2.num) > 50) return (i1.num > i2.num); else return (i1.x < i2.x); } bool compTOLEFT(soldiers i1, soldiers i2) { if(abs(i1.x - i2.x) <= 50000 && abs(i1.num - i2.num) > 50) return (i1.num > i2.num); else return (i1.x > i2.x); } bool compgood(soldiers i1, soldiers i2) { return (i1.num > i2.num); } bool compMEDJUTORIGHT(soldiers i1, soldiers i2) { return (double(i1.x) / double(i1.y) < double(i2.x) / double(i2.y)); } bool compMEDJUTOLEFT(soldiers i1, soldiers i2) { return (double(i1.x) / double(i1.y) > double(i2.x) / double(i2.y)); } void findFIRST() { for(int i = 1; i <= m; i++) if((bad[i].x * bad[i].x + bad[i].y * bad[i].y) < mind) { swap(bad[1], bad[i]); mind = (bad[i].x * bad[i].x + bad[i].y * bad[i].y); } } void findBEST() { for(int i = 2; i <= n; i++) { if(good[i].x > bad[1].x && good[i].y > bad[1].y && sqrt((good[i].x - bad[1].x) * (good[i].x - bad[1].x) + (good[i].y - bad[1].y) * (good[i].y - bad[1].y)) < mind) { swap(good[i], good[1]); mind = sqrt((good[i].x - bad[1].x) * (good[i].x - bad[1].x) + (good[i].y - bad[1].y) * (good[i].y - bad[1].y)); } } return; } void findLIMIT() { if(n != 50000) { LIMIT = good[n].num; return; } LIMIT = ceil(sqrt(SUM)); if(MaxBadnum <= 100) // 0.39 works LIMIT *= 0.388; else if(MaxBadnum <= 360) // 0.757 works LIMIT *= 0.757; else if(MaxBadnum <= 1300) // 0.925 works LIMIT *= 0.925; else if(MaxBadnum <= 4690) // 0.976 works LIMIT *= 0.976; else // 0.993 works LIMIT *= 0.993; return; } void findSECTIONS() { if(MaxBadnum <= 100) // 130 works, 140, 125, 120, 150 and 160 worse SECTIONS = 128; else if(MaxBadnum <= 360) // 130 works, 140, 125, 120, 150 and 160 worse SECTIONS = 130; else if(MaxBadnum <= 1300) // 130 works, 140, 125, 120, 150 and 160 worse SECTIONS = 130; else if(MaxBadnum <= 4690) // 130 works, 140, 125, 120, 150 and 160 worse SECTIONS = 130; else // 130 works, 140, 125, 120, 150 and 160 worse SECTIONS = 130; // prvi: 131 drugi: 130 treci: 127 chetvrti: 130 return; } void organizeM() { DIVIDER = MaxBadvert / SECTIONS; for(int i = 2; i <= m; i++) { M[ceil(bad[i].y / double(DIVIDER))].push_back(bad[i]); } int serial = 0; SECTIONS++; for(int i = 1; i <= SECTIONS; i++) { if(M[i].size() != 0) { serial++; if(serial & 1) sort(M[i].begin(), M[i].end(), compTORIGHT); else sort(M[i].begin(), M[i].end(), compTOLEFT); } } } //void TOVECTOR() //{ // ALIVE.push_back(cur); // ALIVE[0].num = V; // for(int i = n; i >= USED; i--) // ALIVE.push_back(good[i]); // ALIVE[n - USED].num = Vleft - good[n].num - good[USED].num; // return; //} //void SLAUGHTER(ll killed) //{ // return; //} //void findFIRST_SET100() //{ // return; //} //void findBEST_SET100() //{ // return; //} void SET100() { sort(good + 1, good + n + 1, compgood); for(int i = 1; i <= n; i++) GOOD.push_back(good[i]); sort(bad + 1, bad + n + 1, compgood); for(int i = 1; i <= m; i++) BAD.push_back(bad[i]); // for(int i = m-1; i >= 42999; i--) // printf("%d BAD.num = %lld\n", i, BAD[i].num); //freopen("war.out", "w", stdout); printf("%lld\n", m); for(int i = 0; i < n; i++) { printf("bad size: %d\n", BAD.size()); ll best = 0; int bestI = 0; if(BAD.size() == 0) printf("UMRLI SU MAJSTOREEE\n"); int dokle = 0; int j = 0; while(BAD[j].num != GOOD[i].num) j++; //printf("1ovo radi!\n"); // trazi prvog kog mogu da sredim sa GOOD[i] vojnika int y = j; while(BAD[y].num == BAD[j].num) y++; //printf("2ovo radi!\n"); // trazi interval od svih koje mogu da pobedim sa GOOD[i] vojnika for(int k = j; k <= y; k++) { ll distance = sqrt((GOOD[i].x - BAD[k].x) * (GOOD[i].x - BAD[k].x) + (GOOD[i].y - BAD[k].y) * (GOOD[i].y - BAD[k].y)); if(distance > best) { best = distance; bestI = k; } } //printf("3ovo radi!\n"); for(int l = BAD.size() - 1; l >= 1; l--) { if(ceil(sqrt(GOOD[i].num * GOOD[i].num - BAD[l].num * BAD[l].num)) < GOOD[i].num) { printf("PAKAKOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\n"); break; } // PROVERI DA LI TI ODGOVORA TACKA (DA LI JE U DELTOIDU KOJI DOZVOLJAVAMO) ll fTOst = 0; //od formacije do malog ll stTOvt = 0; //od malog do velikog ll fTOvt = 0; //od formacije do velikog fTOvt = best; stTOvt = sqrt((BAD[l].x - BAD[bestI].x) * (BAD[l].x - BAD[bestI].x) + (BAD[l].y - BAD[bestI].y) * (BAD[l].y - BAD[bestI].y)); fTOst = sqrt((GOOD[i].x - BAD[l].x) * (GOOD[i].x - BAD[l].x) + (GOOD[i].y - BAD[l].y) * (GOOD[i].y - BAD[l].y)); if(fTOst + stTOvt <= fTOvt * LUFT100) { //printf("naslo %d\n", l); MEDJUdiv = fTOvt / MEDJUparts; MEDJU[ceil(fTOst / MEDJUdiv)].push_back(BAD[l]); if(BAD.size() > l -1) BAD.erase(BAD.begin() + l), dokle++; printf("dokle: %d\n", dokle); printf("bad size: %d\n", BAD.size()); printf("mojih: %lld; njegovih: %lld\n", GOOD[i].num, BAD[l].num); //MEDJU se radi kao ostatak zadatka, sortirace se po tome gde je u odnosu na dijagonalu normalnu na f-vt } } //printf("ovo nije radilo 1 !\n"); MEDJUparts++; int serial = 0; for(int p = 1; p <= MEDJUparts; p++) //SORTIRANJE { if(MEDJU[p].size() != 0) { serial++; if(serial & 1) sort(MEDJU[p].begin(), MEDJU[p].end(), compMEDJUTORIGHT); else sort(MEDJU[p].begin(), MEDJU[p].end(), compMEDJUTOLEFT); } } printf("MOLIM TE RADI AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); //"MOLIM TE RADI AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" // - Ne radi // - Voli printf("medjuparts: %lld", MEDJUparts); //SORTIRAJ MEDJU PO PRETHODNOM KOMENTARU int t = 1; int outcount = 0; while(outcount < dokle) { int TO = MEDJU[t].size(); if(TO == 0) { printf("mali pakako\n"); printf("outcount: %d; dokle: %d\n", outcount, dokle); continue; } for(int f = 0; f < TO; f++) { printf(" u outcount %d; t = %d; f = %d; %lld %lld ", outcount, t, f, GOOD[i].x, GOOD[i].y); //MOZDA TREBA PROMENITI BROJ VOJNIKA, ALI NEEEEEE BIIIIIII TREBALO GOOD[i].x = MEDJU[t][f].x; GOOD[i].y = MEDJU[t][f].y; printf("%lld %lld %lld\n", GOOD[i].x, GOOD[i].y, GOOD[i].num); outcount++; } t++; } MEDJU.clear(); printf("%lld %lld ", GOOD[i].x, GOOD[i].y); //MOZDA TREBA PROMENITI BROJ VOJNIKA, ALI NEEEEEE BIIIIIII TREBALO GOOD[i].x = BAD[bestI].x; GOOD[i].y = BAD[bestI].y; printf("%lld %lld %lld\n", GOOD[i].x, GOOD[i].y, GOOD[i].num); GOOD[i].num = GOOD[i].num * GOOD[i].num - BAD[bestI].num * BAD[bestI].num; if(GOOD[i].num <= 0) GOOD.erase(GOOD.begin() + i); else sort(GOOD.begin(), GOOD.end(), compgood); //SREDJUJ IH I IZBACUJ IZ VEKTORA SVAKU KOJI RESHISH, I MENJAJ UVEK BROJ VOJNIKA } } // zhelim da gledam svaku formaciju od 90+ i kulu od 90+ (da nije predaleko) i izmedju njih dve (euklid manji, odnos x / y slican, x i y u smeru vece kule) // pobijem kule koje nece uciniti da formacija ne moze da ubije vecu kulu // ovo uradim za sve svoje velike // ostace mu manje, ili isti broj vojnika // za svaku preostalu nadjem najblizu koja moze da ga ubije // AKO VREME BUDE PROBLEM, UZMI PRVO RESENJE KOJE SE NADJE A NIJE GROZNO // ALTERNATIVA ZA 1V1, URADI ONO SHTO DO SADA RADISH ALI CE BITI SA BASH MALO VOJNIKA PA NECE BITI STRASHNO SH // NE ZABORAVI DA ZA SVE VOJNIKE APDEJTASH KOORDINATE I BROJ VOJNIKA // NE ZABORAVI DA POTROSHENE FORMACIJE I UBIJENE KULE BRISHESH IZ VEKTORA void IN() { scanf("%lld%lld", &n, &m); for(int i = 1; i <= n; i++) { scanf("%lld%lld%lld", &good[i].x, &good[i].y, &good[i].num); } for(int i = 1; i <= m; i++) { scanf("%lld%lld%lld", &bad[i].x, &bad[i].y, &bad[i].num); SUM += bad[i].num * bad[i].num; MaxBadnum = max(bad[i].num, MaxBadnum); MaxBadvert = max(bad[i].y, MaxBadvert); } return; } void OUT() { printf("%lld\n", USED - 1 + m); for(int i = 2; i <= USED; i++) printf("%lld %lld %lld %lld %lld\n", good[i].x, good[i].y, good[1].x, good[1].y, good[i].num - good[i-1].num); cur.x = good[1].x; cur.y = good[1].y; V = good[USED].num; ll outcount = 0; printf("%lld %lld %lld %lld %lld\n", cur.x, cur.y, bad[1].x, bad[1].y, V); outcount++; cur.x = bad[1].x; cur.y = bad[1].y; V = ceil(sqrt(V * V - bad[1].num * bad[1].num)); int i = 1; while(outcount != m) { int tosize = M[i].size(); for(int j = 0; j < tosize; j++) { printf("%lld %lld %lld %lld %lld\n", cur.x, cur.y, M[i][j].x, M[i][j].y, V); cur.x = M[i][j].x; cur.y = M[i][j].y; V = ceil(sqrt(V * V - M[i][j].num * M[i][j].num)); outcount++; } i++; } } void TESTOUT() { printf("-----------------------------------------------------\n"); // printf("GOOD GOOD GOOD GOOD GOOD GOOD\n"); // for(int i = 1; i <= n; i++) // printf("GOOD: x = %lld; y = %lld; num = %lld;\n", good[i].x, good[i].y, good[i].num - good[i-1].num); // printf("GOOD GOOD GOOD GOOD GOOD GOOD\n"); printf("MAXBADVERT: %lld\n", MaxBadvert); printf("MAXBADNUM: %lld\n", MaxBadnum); printf("FIRST GOOD: %lld %lld %lld\n", good[1].x, good[1].y, good[1].num); printf("USED: %lld\n", USED); printf("LIMIT: %lld\n", LIMIT); printf("KOMANDE: %lld\n", USED - 1 + m); printf("SUM: %lld\n", SUM); printf("SAKUPLJANJEEE:\n"); for(int i = 2; i <= USED; i++) { // printf("SA: x = %lld; y = %lld; NA x = %lld; y = %lld; V = %lld;\n", good[i].x, good[i].y, good[1].x, good[1].y, good[i].num - good[i-1].num); e += sqrt((good[i].x - good[1].x) * (good[i].x - good[1].x) + (good[i].y - good[1].y) * (good[i].y - good[1].y)) * (good[i].num - good[i-1].num); } cur.x = good[1].x; cur.y = good[1].y; V = good[USED].num; ll outcount = 0; printf("RUSHENJEEE:\n"); // printf("%lld KULA: x = %lld; y = %lld; num = %lld;\n", outcount + 1, bad[1].x, bad[1].y, bad[1].num); // printf("SA: x = %lld; y = %lld; NA x = %lld; y = %lld; V = %lld;\n", cur.x, cur.y, bad[1].x, bad[1].y, V); outcount++; e += sqrt((cur.x - bad[1].x) * (cur.x - bad[1].x) + (cur.y - bad[1].y) * (cur.y - bad[1].y)) * V; cur.x = bad[1].x; cur.y = bad[1].y; V = ceil(sqrt(V * V - bad[1].num * bad[1].num)); int i = 1; while(outcount != m) { int tosize = M[i].size(); for(int j = 0; j < tosize; j++) { // printf("%lld KULA[%d][%d]: x = %lld; y = %lld; num = %lld;\n", outcount + 1, i, j, M[i][j].x, M[i][j].y, M[i][j].num); // printf("SA: x = %lld; y = %lld; NA x = %lld; y = %lld; V = %lld;\n", cur.x, cur.y, M[i][j].x, M[i][j].y, V); outcount++; e += sqrt((cur.x - M[i][j].x) * (cur.x - M[i][j].x) + (cur.y - M[i][j].y) * (cur.y - M[i][j].y)) * V; if(V <= 0) printf("UBIO SEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"); cur.x = M[i][j].x; cur.y = M[i][j].y; V = ceil(sqrt(V * V - M[i][j].num * M[i][j].num)); } i++; } printf("outcount = %lld\n", outcount); //printf("e(no exponent) = %lld\n", e); cout << setprecision(3) << fixed << "e = " << pow(e, (2.0 / 3.0)) << endl; printf("-----------------------------------------------------\n"); } int main() { freopen("war.in", "r", stdin); IN(); // if(MaxBadnum <= 100) // { // SET100(); // return 0; // } mind = 1e10; findFIRST(); mind = 1e10; findBEST(); sort(good + 2, good + n + 1, compgood); for(int i = 2; i <= n; i++) { good[i].num += good[i-1].num; } findLIMIT(); while(good[USED].num < LIMIT && USED < n) USED++; Vleft = good[n].num - LIMIT; good[USED].num = LIMIT; findSECTIONS(); organizeM(); if(test) { TESTOUT(); return 0; } freopen("war.out", "w", stdout); OUT(); return 0; }