#ifdef _WIN32 # define LL "%I64d" #else # define LL "%Ld" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define null NULL #define mp make_pair #define pb(a) push_back(a) #define sz(a) ((int)(a).size()) #define all(a) a.begin() , a.end() #define fi first #define se second #define relaxMin(a , b) (a) = min((a),(b)) #define relaxMax(a , b) (a) = max((a),(b)) #define SQR(a) ((a)*(a)) typedef vector vi; typedef pair pii; typedef long long ll; int N = 1000 , M = 1000 , Q; // Hash typedef unsigned long long ull; #define MAX 1000010 const ull BASE = 1000033; ull bstep[MAX] , bsum[MAX]; #define CODE(w) (w.fi * M + w.se + 1) #define CODE1(w) (w.fi * M + w.se) // Dek. derevo struct node{ pii key; int prior; node *l , *r; // hash ull hash; pii sub_min; int sub_sz; // node(pii _key){ key = _key; prior = ((rand()<<15) + rand()); l = r = null; hash = CODE(key); sub_min = key; sub_sz = 1; } }; void update(node* vr){ if(!vr) return; int Left = (vr->l) ? vr->l->sub_sz : 0; vr->sub_sz = 1; vr->sub_min = vr->key; vr->hash = CODE(vr->key) * bstep[Left]; if(vr->l){ vr->sub_sz += vr->l->sub_sz; relaxMin(vr->sub_min , vr->l->sub_min); vr->hash += vr->l->hash; } if(vr->r){ vr->sub_sz += vr->r->sub_sz; relaxMin(vr->sub_min , vr->r->sub_min); vr->hash += vr->r->hash * bstep[Left+1]; } } //int CNT; void split(node* t, pii key, node*& l, node*& r) { //++CNT; if(!t)l = r = null; else if(key < t->key){ split(t->l , key , l , t->l) , r = t; update(r); } else{ split (t->r , key , t->r , r) , l = t; update(l); } } void insert(node*& t , node* it) { if(!t) t = it; else if(it->prior > t->prior){ split (t , it->key , it->l , it->r) , t = it; update(t); } else{ insert (it->key < t->key ? t->l : t->r, it); update(t); } } void merge(node*& t , node* l , node* r) { if(!l || !r) t = l ? l : r; else if (l->prior > r->prior){ merge(l->r , l->r , r) , t = l; update(t); } else{ merge (r->l, l, r->l), t = r; update(t); } } //// node* target; void dfs(node* vr){ if(vr == null) return; node *L = vr->l , *R = vr->r; //vr->prior = ((rand()<<15) + rand()); //vr->l = vr->r = null; //vr->hash = CODE(vr->key); //vr->sub_min = vr->key; //vr->sub_sz = 1; insert(target , new node(vr->key)); if(L) dfs(L); if(R) dfs(R); } //// node* unite(node* l , node* r) { //++CNT; if(!l || !r)return l ? l : r; if(l->sub_sz < r->sub_sz) swap(l , r); target = l; dfs(r); return l; /* if(l->prior < r->prior)swap(l , r); node *lt , *rt; split(r, l->key, lt, rt); l->l = unite (l->l, lt); l->r = unite (l->r, rt); update(l); return l; */ } // tree ops void out(pii w){ cout<hash; hc -= CODE(root->sub_min) * bsum[root->sub_sz - 1]; return hc; } // solution map cnt; ll ALL; void rem(ull w){ ll& how = cnt[w]; ALL -= (how*(how-1)) >> 1; --how; ALL += (how*(how-1)) >> 1; } void add(ull w){ ll& how = cnt[w]; ALL -= (how*(how-1)) >> 1; ++how; ALL += (how*(how-1)) >> 1; } node* combine(node* f , node* s){ ull h1 = get_hash(f); ull h2 = get_hash(s); if(f != null) rem(h1); if(s != null) rem(h2); f = unite(f , s); add(get_hash(f)); return f; } // UF #define UF_MAX 1001000 int par[UF_MAX]; int get_par(int vr){ return par[vr] == vr ? vr : par[vr] = get_par(par[vr]); } void merge(int a , int b){ a = get_par(a) , b = get_par(b); par[a] = b; } int in[1010][1010] , act[1010][1010]; vector< pair > event; // Querries vi qd; vector output; int dlt[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; map trees; int main(){ freopen("2014.in" , "r" , stdin); freopen("2014.out" , "w" , stdout); // init bstep[0] = 1; for(int i=1;i //N = M = 1000; scanf("%d%d" , &N , &M); for(int i=0;i 0) event.pb(mp(in[i][j] - 1 , mp(i,j))); sort(all(event)); //printf("%.3lf\n" , (clock() - 0.0)/CLOCKS_PER_SEC); scanf("%d" , &Q); //Q = 100000; qd.resize(Q+1); output.resize(Q+1); qd[Q] = 1000000005; for(int i=0;i=0;--i){ int tim = qd[i]; while(!event.empty() && event.back().fi >= tim){ pii use = event.back().se; event.pop_back(); node* cur_tree = new node(use); trees[get_par(CODE1(use))] = cur_tree; act[use.fi][use.se] = true; add(get_hash(cur_tree)); for(int p=0;p<4;++p){ pii neo(use.fi + dlt[p][0] , use.se + dlt[p][1]); if(neo.fi < 0 || neo.fi >= N || neo.se < 0 || neo.se >= M) continue; if(!act[neo.fi][neo.se]) continue; int fid = get_par(CODE1(use)); int sid = get_par(CODE1(neo)); if(fid == sid) continue; cur_tree = combine(trees[fid] , trees[sid]); trees.erase(fid) , trees.erase(sid); merge(fid , sid); trees[get_par(CODE1(use))] = cur_tree; } } output[i] = ALL; } /* for(map::iterator it = cnt.begin(); it != cnt.end(); ++it){ cout<fi<<' '<se<