LA 3525

LA 3525 - Wild West

 * [Problem Link]

Summary
There are $$M^3$$ gunmen characterized by three different skills, each ranging from 1 to M. A subset containing N of these gunmen are The Bad Guys. We want to select one of the other gunmen to be a Hero. The Hero must beat each of the Bad Guys in at least one skill (not necessarily the same skill for all Bad Guys).

The task is to compute the number of gunmen that can be selected to be the Hero.

Explanation
Consider a Bad Guy with skills [a,b,c]. The set of gunmen that can't beat him is a cuboid with opposite corners [1,1,1] and [a,b,c]. The union U of all these cuboids is exactly the set of gunmen that can't be heroes. Thus the answer is $$M^3$$ minus the volume of U.

We can compute the volume of U in $$O(M \log M)$$ by sweeping in one direction and maintaining the intersection of the sweeping plane and U in some tree-like structure.

Implementations
In C++, STL sets can be used, there is no need to implement the tree-like structure. --- my code accepted at archive -- // code of myprasanna using namespace std;
 * 1) include
 * 2) include
 * 3) include
 * 4) include
 * 5) include
 * 6) include
 * 7) include
 * 8) include
 * 9) include 
 * 10) include


 * 1) define V(x) vector< x >
 * 2) define LET(x,a) __typeof(a) x(a)
 * 3) define FOR(i,a,b) for(LET(i,(a));i!=(b);++i)
 * 4) define REP(i,n) FOR(i,0,n)
 * 5) define EACH(it,v) FOR(it,(v).begin,(v).end)
 * 6) define ALL(f,x) ({ bool _ok = true ; f if( ! (x) ) { _ok=false; break; } ; _ok; })
 * 7) define EXISTS(f,x) ({ book _ok=false; f if( x ) { _ok=true;break;} ; _ok; })
 * 8) define COUNT(f,x) ({int _cnt=0; f if (x) ++_cnt; _cnt; })
 * 9) define sz size
 * 10) define cs c_str
 * 11) define pb push_back
 * 12) define GI ({int t;scanf("%d",&t); t;})
 * 13) define INF (int)1e9
 * 14) define MIN(f,x) ({int k=INF;f k<?=(x);k;})
 * 15) define MAX(f,x) ({int k=0;f k>?=(x);k;})
 * 16) define isi(s) ({int i;sscanf((s).CS,"%d",&i)==1;})
 * 17) define s2i(s) ({int i;sscanf((s).CS,"%d",&i);i;})
 * 18) define dbg(x) cout << #x << " -> " << (x) << "\t";
 * 19) define dbge(x) cout << #x << " -> " << (x) << endl;

typedef V(int) VI; typedef V(string) VS; typedef V(VI) VII; typedef long long LL; typedef long double LD; typedef pair PII; typedef pair PIII; LL n, m; LL ans, area; PIII P[MN]; map Ht;
 * 1) define MN ((int)1e5+10)

void ins(int x, int y) { while(1) { LET(it, Ht.lower_bound(x)); int cy = it->second; if(it == Ht.begin) break; --it; if(it->second > y) break; int a = it->first, b = it->second; assert(it != Ht.begin); --it; a -= it->first ; assert(a >= 0); b -= cy; assert( b >= 0); ++ it; //dbg(it->first); dbge(it->second); assert( a * b >= 0); area -= a* LL(b); Ht.erase(it); }	{		LET(it, Ht.lower_bound(x)); if(it->second >= y) return; int na = it->first, nb = it->second; assert(it != Ht.begin); --it; assert((x - it->first) * LL(y - nb) >= 0); area += (x - it->first) * LL(y - nb); Ht[x] = y;	} }

int main { while( n = GI ) { m = GI; ans = area = 0; Ht.clear; Ht[0] = 1+m; Ht[m] = 0; REP(i,n) P[i].first = GI, P[i].second.first = GI, P[i].second.second = GI; sort(P,P+n);reverse(P,P+n); int pp = 0; for(int fir = m; fir >= 1; fir--) { // first co-ordinate goes in decreasing order. while( pp < n && fir == P[pp].first ) { ins(P[pp].second.first, P[pp].second.second); pp ++; }			ans += (m*m - area); assert( area <= m*m ); //dbg(fir); dbg(area); dbge(m*m - area); }		cout << ans << endl; }	return 0; }

Input
3 10 2 8 5 6 3 5 1 3 9 1 3 2 2 2 1 10000 2 2 2 0 0

Output
848 19 999999999992