#include #include #include #include #include #define HORNI 1 #define DOLNI 2 #define LEVA 1 #define PRAVA 2 using namespace std; struct vhrana_t { // vodorovná hrana skvrny int radek; int lsloupec; int psloupec; int typ; // dolní nebo horní int flek; // číslo fleku, kterému tato hrana přísluší vhrana_t(int _radek, int _lsloupec, int _psloupec, int _typ, int _flek) : radek(_radek), lsloupec(_lsloupec), psloupec(_psloupec), typ(_typ), flek(_flek) {} bool operator<(const vhrana_t &hrana) const { // třídíme od zdola nahoru return radek vhrany; // seznam všech vodorovných hran vector barvy(N+1); // pro převod čísla fleku na jeho barvu vector obsahy(N+1,0); // počet jednotek zabíraných fleky vhrany.push_back(vhrana_t(0,0,W,DOLNI,0)); // plocha trička je považována za nultý flek vhrany.push_back(vhrana_t(H,0,W,HORNI,0)); barvy[0]=0; for (int i=1;i<=N;i++) { int ldr, lds, phr, phs, barva; scanf("%d%d%d%d%d",&lds,&ldr,&phs,&phr,&barva); vhrany.push_back(vhrana_t(ldr,lds,phs,DOLNI,i)); vhrany.push_back(vhrana_t(phr,lds,phs,HORNI,i)); barvy[i]=barva; } sort(vhrany.begin(),vhrany.end()); list shrany; vector::iterator vhrana; int vpozice=-1; for (vhrana=vhrany.begin();vhrana!=vhrany.end();++vhrana) { // procházíme vodorovné hrany zdola nahoru list::iterator shrana; if (vpozice>=0) { // pokud se nejedná o první hranu int vyska=vhrana->radek-vpozice; // výška vodorovného pruhu int spozice=-1; set halda; // ze standarní haldy nelze debírat libovolné prvky for (shrana=shrany.begin();shrana!=shrany.end();++shrana) { // procházíme svislé hrany zleva doprava if (spozice>=0) obsahy[*halda.rbegin()] // *halda.rbegin() je maximální prvek v haldě +=(shrana->sloupec-spozice)*vyska; if (shrana->typ == LEVA) // přesně podle popisu řešení halda.insert(shrana->flek); else halda.erase(shrana->flek); spozice=shrana->sloupec; } } if (vhrana->typ == DOLNI) { // přesně podle popisu řešení list pomoc; pomoc.push_back(shrana_t(vhrana->lsloupec,LEVA,vhrana->flek)); pomoc.push_back(shrana_t(vhrana->psloupec,PRAVA,vhrana->flek)); shrany.merge(pomoc); // zatřídíme svislé hrany do množiny } else { for (shrana=shrany.begin();shrana!=shrany.end();++shrana) while (shrana->flek==vhrana->flek) // odstraníme příslušné hrany z množiny shrana=shrany.erase(shrana); } vpozice=vhrana->radek; } printf("Čistého trička zůstalo %d jednotek\n", obsahy[0]); for (int i=1;i<=N;i++) // neefektivní způsob, ale časovou složitost nezhorší if (barvy[i]!=0) { int barva=barvy[i]; int celkem=0; for (int j=i;j<=N;j++) if (barvy[j]==barva) { celkem+=obsahy[j]; barvy[j]=0; } printf("Barva %d zabíra %d jednotek\n",barva,celkem); } return 0; }