Submission #823664

#TimeUsernameProblemLanguageResultExecution timeMemory
823664oscar1fRectangles (IOI19_rect)C++17
0 / 100
5082 ms483656 KiB
#include<bits/stdc++.h>
#include "rect.h"

using namespace std;
using ll=long long;

const int TAILLE_MAX=2505,DECA=(1<<12),INFINI=1000*1000*1000;
ll rep;
int nbLig,nbCol;
int val[TAILLE_MAX][TAILLE_MAX];
int limite[TAILLE_MAX][TAILLE_MAX][4];
int limCalc[TAILLE_MAX][2];
int arbreMin[TAILLE_MAX][2*DECA],arbreMax[TAILLE_MAX][2*DECA],arbreSom[2*DECA];
vector<int> possi;
set<int> enCours;
set<int>::iterator it;
vector<int> prop[TAILLE_MAX][TAILLE_MAX];

int calcMin(int tab,int deb,int fin) {
	if (deb==fin) {
		return arbreMin[tab][deb];
	}
	if (deb%2==1) {
		return min(arbreMin[tab][deb],calcMin(tab,deb+1,fin));
	}
	if (fin%2==0) {
		return min(arbreMin[tab][fin],calcMin(tab,deb,fin-1));
	}
	return calcMin(tab,deb/2,fin/2);
}

int calcMax(int tab,int deb,int fin) {
	if (deb==fin) {
		return arbreMax[tab][deb];
	}
	if (deb%2==1) {
		return max(arbreMax[tab][deb],calcMax(tab,deb+1,fin));
	}
	if (fin%2==0) {
		return max(arbreMax[tab][fin],calcMax(tab,deb,fin-1));
	}
	return calcMax(tab,deb/2,fin/2);
}

int calcSom(int deb,int fin) {
	if (deb==fin) {
		return arbreSom[deb];
	}
	if (deb%2==1) {
		return arbreSom[deb]+calcSom(deb+1,fin);
	}
	if (fin%2==0) {
		return arbreSom[fin]+calcSom(deb,fin-1);
	}
	return calcSom(deb/2,fin/2);
}

void ajout(int pos,int coeff) {
	pos+=DECA;
	arbreSom[pos]+=coeff;
	while (pos>1) {
		pos/=2;
		arbreSom[pos]=arbreSom[2*pos]+arbreSom[2*pos+1];
	}
}

void calc(int ligHaut,int ligBas,int colGau,int colDroi) {
	//cout<<ligHaut<<" "<<ligBas<<" "<<colGau<<" "<<colDroi<<" : ";
	for (int i=colGau-1;i<=colDroi+1;i++) {
		limCalc[i][0]=calcMax(i,DECA+ligHaut,DECA+ligBas);
		limCalc[i][1]=calcMin(i,DECA+ligHaut,DECA+ligBas);
		//cout<<i<<" "<<limCalc[i][0]<<" "<<limCalc[i][1]<<"   ";
	}
	//cout<<endl;
	vector<tuple<int,int,int>> listeCol;
	for (int i=colGau-1;i<=colDroi+1;i++) {
		listeCol.push_back(make_tuple(i,1,i));
		listeCol.push_back(make_tuple(limCalc[i][0]-1,-1,i));
	}
	sort(listeCol.begin(),listeCol.end(),[&](tuple<int,int,int> a,tuple<int,int,int> b) {
		if (get<0>(a)>get<0>(b)) {
			return true;
		}
		if (get<0>(a)<get<0>(b)) {
			return false;
		}
		return get<0>(a)>get<0>(b);
	});
	for (auto k:listeCol) {
		//cout<<get<0>(k)<<" "<<get<1>(k)<<" "<<get<2>(k)<<"   ";
		if (get<1>(k)==-1) {
			ajout(get<2>(k),-1);
		}
		else {
			if (limCalc[get<0>(k)][1]+1>=get<0>(k)+2) {
				//cout<<"!";
				rep+=(ll)calcSom(DECA+get<0>(k)+2,DECA+limCalc[get<0>(k)][1]+1);
			}
			ajout(get<0>(k),1);
		}
	}
	//cout<<endl;
}

ll count_rectangles(vector<vector<int>> a) {
	nbLig=a.size();
	nbCol=a[0].size();
	if (nbLig<=2 or nbCol<=2) {
		return 0;
	}
	for (int i=0;i<nbLig;i++) {
		for (int j=0;j<nbCol;j++) {
			val[i][j]=a[i][j];
		}
	}
	for (int i=0;i<nbLig;i++) {
		enCours.clear();
		enCours.insert(-1);
		possi.clear();
		for (int j=0;j<nbCol;j++) {
			possi.push_back(j);
		}
		sort(possi.begin(),possi.end(),[&](int a,int b) {
			if (val[i][a]>val[i][b]) {
				return true;
			}
			if (val[i][a]<val[i][b]) {
				return false;
			}
			return a<b;
		});
		for (int j:possi) {
			it=enCours.upper_bound(j);
			it--;
			limite[i][j][0]=(*it)+1;
			//cout<<i<<" "<<j<<" : "<<limite[i][j][0]<<endl;
			enCours.insert(j);
		}
		enCours.clear();
		enCours.insert(nbCol);
		sort(possi.begin(),possi.end(),[&](int a,int b) {
			if (val[i][a]>val[i][b]) {
				return true;
			}
			if (val[i][a]<val[i][b]) {
				return false;
			}
			return a>b;
		});
		for (int j:possi) {
			it=enCours.upper_bound(j);
			limite[i][j][1]=(*it)-1;
			//cout<<i<<" "<<j<<" : "<<limite[i][j][0]<<endl;
			enCours.insert(j);
		}
	}
	for (int j=0;j<nbCol;j++) {
		enCours.clear();
		enCours.insert(-1);
		possi.clear();
		for (int i=0;i<nbLig;i++) {
			possi.push_back(i);
		}
		sort(possi.begin(),possi.end(),[&](int a,int b) {
			if (val[a][j]>val[b][j]) {
				return true;
			}
			if (val[a][j]<val[b][j]) {
				return false;
			}
			return a<b;
		});
		for (int i:possi) {
			it=enCours.upper_bound(i);
			it--;
			limite[i][j][2]=(*it)+1;
			//cout<<i<<" "<<j<<" : "<<limite[i][j][0]<<endl;
			enCours.insert(i);
		}
		enCours.clear();
		enCours.insert(nbLig);
		sort(possi.begin(),possi.end(),[&](int a,int b) {
			if (val[a][j]>val[b][j]) {
				return true;
			}
			if (val[a][j]<val[b][j]) {
				return false;
			}
			return a>b;
		});
		for (int i:possi) {
			it=enCours.upper_bound(i);
			limite[i][j][3]=(*it)-1;
			//cout<<i<<" "<<j<<" : "<<limite[i][j][0]<<endl;
			enCours.insert(i);
		}
	}
	int deb,pos;
	for (int i=0;i<nbCol;i++) {
		for (int j=0;j<2*DECA;j++) {
			arbreMin[i][j]=nbCol-1;
			arbreMax[i][j]=0;
		}
		for (int j=0;j<nbLig;j++) {
			arbreMin[i][DECA+j]=limite[j][i][1];
			arbreMax[i][DECA+j]=limite[j][i][0];
		}
		for (int j=DECA-1;j>0;j--) {
			arbreMin[i][j]=min(arbreMin[i][2*j],arbreMin[i][2*j+1]);
			arbreMax[i][j]=max(arbreMax[i][2*j],arbreMax[i][2*j+1]);
		}
	}
	possi.clear();
	for (int i=0;i<nbLig;i++) {
		possi.push_back(i);
	}
	int lig;
	for (int col=1;col<nbCol-1;col++) {
		enCours.clear();
		enCours.insert(-INFINI);
		enCours.insert(INFINI);
		sort(possi.begin(),possi.end(),[&](int a,int b) {
			if (val[a][col]>val[b][col]) {
				return true;
			}
			if (val[a][col]<val[b][col]) {
				return false;
			}
			return a<b;
		});
		//cout<<col<<" : ";
		for (int i=0;i<nbLig;i++) {
			lig=possi[i];
			//cout<<lig<<" ";
			it=enCours.upper_bound(lig);
			if ((*it)!=INFINI and (*it)-lig>1 and (i==nbLig-1 or val[possi[i]][col]>val[possi[i+1]][col] or possi[i+1]>(*it))) {
				//cout<<"! "<<lig+1<<" "<<(*it)-1<<" "<<col<<endl;
				prop[lig+1][(*it)-1].push_back(col);
			}
			it--;
			if ((*it)!=-INFINI and lig-(*it)>1) {
				prop[(*it)+1][lig-1].push_back(col);
				//cout<<"! "<<(*it)+1<<" "<<lig-1<<" "<<col<<endl;
			}
			enCours.insert(lig);
		}
		//cout<<endl;
	}

	for (int ligHaut=1;ligHaut<nbLig-1;ligHaut++) {
		for (int ligBas=ligHaut;ligBas<nbLig-1;ligBas++) {
			prop[ligHaut][ligBas].push_back(INFINI);
			pos=0;
			while (prop[ligHaut][ligBas][pos]!=INFINI) {
				deb=pos;
				while (prop[ligHaut][ligBas][pos]!=INFINI and prop[ligHaut][ligBas][pos+1]==prop[ligHaut][ligBas][pos]+1) {
					pos++;
				}
				calc(ligHaut,ligBas,prop[ligHaut][ligBas][deb],prop[ligHaut][ligBas][pos]);
				pos++;
			}
		}
	}
	return rep;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...