#include # define endl '\n' # define clr(x,a) memset(x,a,sizeof(x)) # define vi vector # define linija cout << "_________________________________\n"; # define all(a) a.begin(), a.end() # define deb(x) cout<<#x<<"=="< inline T na2(T x){return x*x;} typedef long long ll; int n, m, c, delilac = 20, test, suma_u, tg, brN; //broj na koliko delim bool osnovni_slucaj_flag; int grupev[410][15000], grupek[410][15000], kojitest[6] = {0, 20, 20, 10, 4, 2}, niz[mxN];; int poredak[110] = {0,23,24,34,33,32,22,12,13,14,15,25,35,45,44,43,42,41,31,21,11,1,2,3,4,5,6,7,8,9,10,20,19,18,17,16,26,27,28,29,30,40,39,38,37,36,46,47,48,49,50,60,59,58,57,56,55,54,53,52,51,61,62,63,64,65,66,67,68,69,70,80,90,100,99,98,97,96,95,94,93,92,91,81,71,72,82,83,73,74,84,85,75,76,86,87,88,89,79,78,77}; ll GLOBALX, GLOBALY; struct Tacka{ ll x, y, val; int id; }kule[mxN], vojska[mxN], vojnik, kula, mali[mxN], veliki[mxN]; struct Komanda{ int x1, x2, y1, y2, val; }kom[1000006]; struct Tacka2{ ll udaljenost; int id, val; }potencijalni_vojnici[20600], ptv; //udaljenost, brojnost bool cmp_u_odnosu_na_datu_tacku(Tacka a, Tacka b){return na2(a.x - GLOBALX)+na2(a.y-GLOBALY) < na2(b.x - GLOBALX)+na2(b.y-GLOBALY);} bool cmp_tacke_val(Tacka a, Tacka b){return a.val < b.val;} bool cmp_first_float(Tacka2 a, Tacka2 b){return a.udaljenost < b.udaljenost;} bool cmp_first_int(pair a, pair b){return a.first < b.first;} void unos(){ cout << setprecision(2) << fixed; freopen("war.in", "r", stdin); sc("%d %d", &n, &m); for(int i = 1; i <= n; i++){ sc("%lld %lld %lld", &vojska[i].x, &vojska[i].y, &vojska[i].val); vojska[i].id = i; suma_u += vojska[i].val; } ll maxv = 0; for(int i = 1; i <= m; i++){ sc("%d %d %d", &kule[i].x, &kule[i].y, &kule[i].val); maxv = max(maxv, kule[i].val); kule[i].id = i; } if(maxv <= 100) test = 1; else if(maxv <= 360) test = 2; else if(maxv <= 1300) test = 3; else if(maxv <= 4690) test = 4; else test = 5; } float dist(ll x1, ll y1, ll x2, ll y2){ return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ); } ll dist2(ll x1, ll y1, ll x2, ll y2){ return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2); } int borba(ll q, ll p){ /// q napada p! ll koren = q*q - p*p; if(koren < 0) exit(1); return ceil( sqrt(koren) ); } void osnovni_slucaj(){ c = 0; int potrebno = 1e9, l=1, r=1e9, mid; ll koren, p; while(l <= r){ mid = (l+r)/2; p = mid; for(int i = 1; i <= m; i++){ koren = p * p - kule[i].val * kule[i].val; if(koren < 0) break; p = ceil( sqrt(koren) ); } if(koren >= 0){ r = mid - 1; potrebno = min(potrebno, mid); } else l = mid + 1; } for(int i = 2; i <= n; i++){ c++; kom[c].x1 = vojska[i].x; kom[c].y1 = vojska[i].y; kom[c].x2 = vojska[1].x; kom[c].y2 = vojska[1].y; kom[c].val = vojska[i].val; vojska[1].val += vojska[i].val; if(vojska[1].val >= potrebno) break; } for(int i = 1; i <= m; i++){ c++; kom[c].x1 = vojska[1].x; kom[c].y1 = vojska[1].y; kom[c].x2 = kule[i].x; kom[c].y2 = kule[i].y; kom[c].val = vojska[1].val; vojska[1].x = kule[i].x; vojska[1].y = kule[i].y; vojska[1].val = borba(vojska[1].val, kule[i].val); } } void ispis(){ freopen("war.out", "w", stdout); if(osnovni_slucaj_flag){ osnovni_slucaj(); } pr("%d\n", c); for(int i = 1; i <= c; i++){ pr("%d %d %d %d %d\n", kom[i].x1, kom[i].y1, kom[i].x2, kom[i].y2, kom[i].val); } } void dodaj_kom(int x1, int y1, int x2, int y2, int val){ c++; kom[c].x1 = x1; kom[c].y1 = y1; kom[c].x2 = x2; kom[c].y2 = y2; kom[c].val = val; } void dodaj_kom_id_vojska(int id1, int id2){ ///mora id vojnikaa c++; kom[c].x1 = vojska[id1].x; kom[c].y1 = vojska[id1].y; kom[c].x2 = vojska[id2].x; kom[c].y2 = vojska[id2].y; kom[c].val = vojska[id1].val; } void dodaj_kom_id_vojska_kula(int &x, int &y, int id2, int val){ c++; kom[c].x1 = x; kom[c].y1 = y; kom[c].x2 = kule[id2].x; kom[c].y2 = kule[id2].y; kom[c].val = val; x = kule[id2].x; y = kule[id2].y; } void razdvoj_tacke(){ int id_tacke, razapet = 1000000000 / delilac; for(int i = 1; i <= n; i++){ id_tacke = (vojska[i].y/razapet) * delilac + vojska[i].x/razapet + 1; grupev[id_tacke][++grupev[id_tacke][0]] = vojska[i].id; } for(int i = 1; i <= m; i++){ id_tacke = (kule[i].y/razapet) * delilac + kule[i].x/razapet + 1; grupek[id_tacke][++grupek[id_tacke][0]] = kule[i].id; } // cout <<"razapno sam ga\n"; } int formula(){ //ovo nije ni za kurac, al daj boze vise poencicacaacaaa! int l=1, r=0, mid, ret = 1e9, kraj = grupek[tg][0]; for(int i = 1; i <= grupev[tg][0]; i++) r += vojska[ grupev[tg][i] ].val; ll p, koren; while(l <= r){ p = mid = (l+r)/2; for(int i = 1; i <= kraj; i++){ koren = p * p - kule[ grupek[tg][i] ].val * kule[ grupek[tg][i] ].val; if(koren < 0) break; p = ceil( sqrt(koren) ); } if(koren >= 0){ r = mid - 1; ret = min(ret, mid); } else l = mid + 1; } if(ret == 1e9) ret = -1; return ret; } void MST_kurcoglavi(){ ll duzina, trendist; int l = grupek[tg][0]-1, idx, cvor; niz[1] = grupek[tg][1]; swap(grupek[tg][1], grupek[tg][ grupek[tg][0] ]); for(int i = 2; i <= grupek[tg][0]; i++){ duzina = 1e18; for(int j = 1; j <= l; j++){ trendist = dist2(kule[ grupek[tg][j] ].x, kule[ grupek[tg][j] ].y, kule[niz[i-1]].x, kule[ niz[i-1] ].y); if(trendist < duzina){ duzina = trendist; cvor = grupek[tg][j]; idx = j; } } niz[i] = cvor; swap(grupek[tg][idx], grupek[tg][l]); l--; } for(int i = 1; i <= grupek[tg][0]; i++) grupek[tg][i] = niz[i]; } void skupljanje_vojnika(){ ll t, mojet; //potrebno za ubijanje svih int id_kule, broj_grupa; broj_grupa = delilac * delilac; for(tg = 1; tg <= broj_grupa; tg++){ // cout << "idi radi formulu\n"; MST_kurcoglavi(); t = formula(); if(t == -1){ osnovni_slucaj_flag = 1; return; } mojet = t; id_kule = grupek[tg][1]; //kula koju napadam for(int i = 1; i <= grupev[tg][0]; i++){ ptv.udaljenost = dist2(vojska[grupev[tg][i]].x, vojska[grupev[tg][i]].y, kule[id_kule].x, kule[id_kule].y); ptv.id = grupev[tg][i]; ptv.val = vojska[ grupev[tg][i] ].val; potencijalni_vojnici[i] = ptv; } sort(potencijalni_vojnici+1, potencijalni_vojnici+1+grupev[tg][0], cmp_first_float); t -= potencijalni_vojnici[1].val; for(int i = 2; i <= grupev[tg][0]; i++){ if(t <= 0) break; dodaj_kom_id_vojska(potencijalni_vojnici[i].id, potencijalni_vojnici[1].id); } t = mojet; int mx, my; mx = vojska[potencijalni_vojnici[1].id].x, my = vojska[potencijalni_vojnici[1].id].y; for(int i = 1; i <= grupek[tg][0]; i++){ dodaj_kom_id_vojska_kula (mx, my, grupek[tg][i], t); t = borba(t, kule[grupek[tg][i]].val ); } } } void algic1(){ delilac = kojitest[test]; razdvoj_tacke(); //trebalo bi po 8x8 da ga razdvoji skupljanje_vojnika(); //skupim ih na jedno mesto, i prodjem } void dfs(){ if(tg > delilac*delilac) return; int id_tg = poredak[tg]; int l, kraj, idx, cvor; ll trendist, duzina; l = kraj = grupek[id_tg][0]; if(brN == 0){ niz[++brN] = grupek[id_tg][1]; swap(grupek[id_tg][1], grupek[id_tg][ grupek[id_tg][0] ]); kraj--; l--; } for(int i = 1; i <= kraj; i++){ duzina = 1e18; for(int j = 1; j <= l; j++){ trendist = dist2(kule[ grupek[id_tg][j] ].x, kule[ grupek[id_tg][j] ].y, kule[ niz[brN-1] ].x, kule[ niz[brN-1] ].y); if(trendist < duzina){ duzina = trendist; cvor = grupek[id_tg][j]; idx = j; } } niz[++brN] = cvor; swap(grupek[id_tg][idx], grupek[id_tg][l]); l--; } tg++; dfs(); } void algoritam_za_velike_kule(){ for(int i = 1; i <= 100; i++) poredak[i] = i; delilac = 10; razdvoj_tacke(); brN = 0; tg = 1; dfs(); // cout << kule[niz[1]].x << ", " << kule[niz[1]].y<= 0){ r = mid - 1; potrebno = min(potrebno, mid); } else l = mid + 1; } int idx; ll duzina = 1e18, trendist; for(int i = 1; i <= n; i++){ trendist = dist2(kule[ niz[1] ].x, kule[ niz[1] ].y, vojska[i].x, vojska[i].y); if(trendist < duzina){ duzina = trendist; idx = i; } } GLOBALX = vojska[idx].x; GLOBALY = vojska[idx].y; sort(vojska+1, vojska+1+n, cmp_u_odnosu_na_datu_tacku); for(int i = 1; i <= n; i++){ if(idx == i) continue; c++; kom[c].x1 = vojska[i].x; kom[c].y1 = vojska[i].y; kom[c].x2 = vojska[idx].x; kom[c].y2 = vojska[idx].y; kom[c].val = vojska[i].val; vojska[idx].val += vojska[i].val; if(vojska[idx].val >= potrebno) break; } for(int i = 1; i <= m; i++){ c++; kom[c].x1 = vojska[idx].x; kom[c].y1 = vojska[idx].y; kom[c].x2 = kule[ niz[i] ].x; kom[c].y2 = kule[ niz[i] ].y; kom[c].val = vojska[idx].val; vojska[idx].x = kule[ niz[i] ].x; vojska[idx].y = kule[ niz[i] ].y; vojska[idx].val = borba(vojska[idx].val, kule[ niz[i] ].val); } } void mali_kurci(){ int brvel, brmal, sumavojske, sumakula; brvel = brmal = sumavojske = sumakula = 0; for(int i = 1; i <= n; i++){ sumakula += kule[i].val; sumavojske += vojska[i].val; if(kule[i].val <= 20) mali[++brmal] = kule[i]; if(vojska[i].val >= 80) veliki[++brvel] = vojska[i]; } //velike vojske na male kule ! ! ! sort(mali+1, mali+1+brmal, cmp_tacke_val); //mozda bacim neki sortic ll najbliza_dist, trendist; int cvor; // cout << sumavojske << " " << sumakula << endl; for(int i = 1; i <= brmal; i++){ //mozda treba ubaciti racunanje po scoru (to bi bilo naopti) ali videcemo zbog vremena if(sumavojske >= sumakula) break; najbliza_dist = 1e17; for(int j = 1; j <= brvel; j++){ trendist = dist2(mali[i].x, mali[i].y, veliki[j].x, veliki[j].y); if(trendist < najbliza_dist){ najbliza_dist = trendist; cvor = j; } } c++; kom[c].x1 = veliki[cvor].x; kom[c].y1 = veliki[cvor].y; kom[c].x2 = mali[i].x; kom[c].y2 = mali[i].y; kom[c].val = veliki[cvor].val; veliki[cvor].x = mali[i].x; veliki[cvor].y = mali[i].y; sumavojske -= veliki[cvor].val; veliki[cvor].val = borba(veliki[cvor].val, mali[i].val); sumavojske += veliki[cvor].val; if(veliki[cvor].val < 60){ swap(veliki[cvor], veliki[brvel]); brvel--; } sumakula -= mali[i].val; } // cout << sumavojske << " " << sumakula << endl; } void solve(){ // if(test == 1) mali_kurci(); if(test <= 4) algic1(); else algoritam_za_velike_kule(); } int main(){ unos(); solve(); ispis(); return 0; }