Submission #1276593

#TimeUsernameProblemLanguageResultExecution timeMemory
1276593justinlgl20Sandcastle 2 (JOI22_ho_t5)C++20
100 / 100
2771 ms362856 KiB
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define all(x) (x).begin(), (x).end()
#define pii pair<int, int>
#define f first
#define s second
 
template<template<typename> class Container, typename G>
ostream& operator<<(ostream& os, Container<G> x) {int f=0;os<<'{';for(auto&i:x)os<<(f++ ? ", " : ""),os<<i;os<<"}";return os;}
void _print() {cerr << "]\n";}
template<typename T, typename... V>
void _print(T t, V... v) {cerr << t; if (sizeof...(v)) cerr <<", "; _print(v...);}
#ifdef DEBUG
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif

int lg[500005];
void preprocess(){
	lg[1]=0;
	for(int i=2;i<=500000;i++)lg[i]=lg[i/2]+1;
}

template<typename T>
struct sparseTable{
	vector<vector<sparseTable>>t;
	T op(T a, T b){
		return min(a,b);
	}
	bool end=0;T val;int n;
	template<typename... A> sparseTable(int n,A... args){ this->n=n;t.assign(lg[n]+1,vector<sparseTable>(n,sparseTable(args...))); }
	sparseTable(){end=1;};
	template<typename... A> void upd(int pos,A... args){ t[0][pos].upd(args...); }
	void upd(T v){ val=v; }
	void build(){
		if(end)return; for(int i=0;i<n;i++){t[0][i].build();}
		for(int i=1;i<t.size();i++){ for(int l=0,r=l+(1<<i)-1;r<n;l++,r++){ t[i][l]=t[i-1][l]+t[i-1][l+(1<<(i-1))]; } }
	}
	template<typename... A> T query(int l,int r,A... args){
		int v=lg[r-l+1]; return op(t[v][l].query(args...),t[v][r-(1<<v)+1].query(args...));
	}
	T query(){ return val; }
	sparseTable operator+(sparseTable other){
		sparseTable res=other; if(end){ res.val=op(val,other.val); return res;}
		for(int i=0;i<t.size();i++){ for(int j=0;j<n;j++){ res.t[i][j]=res.t[i][j]+t[i][j]; } }
		return res;
	};
};

int32_t main() {
	int n,m;cin>>n>>m;
	vector<vector<int>>a;
	if(n<m){
		a=vector<vector<int>>(n,vector<int>(m,0));for(int i=0;i<n;i++)for(int j=0;j<m;j++)cin>>a[i][j];
	}else{
		swap(n,m);
		a=vector<vector<int>>(n,vector<int>(m,0));for(int i=0;i<m;i++)for(int j=0;j<n;j++)cin>>a[j][i];
	}
	vector<vector<int>>norm(n,vector<int>(m,0));
	vector<vector<int>>psa(n,vector<int>(m,0));
	vector<vector<vector<int>>>dir(4,vector<vector<int>>(n,vector<int>(m,0)));
	vector<vector<vector<int>>>ppp(4,vector<vector<int>>(n,vector<int>(m,0)));
	vector<int>dx={-1,1,0,0};
	vector<int>dy={0,0,-1,1};
	function<int(int,int)>get=[&](int i,int j){
		if(0<=i and i<n and 0<=j and j<m)return a[i][j];
		return (int)1e9;
	};
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			norm[i][j]=a[i][j];
			for(int k=0;k<4;k++)dir[k][i][j]=a[i][j];
			for(int k=0;k<4;k++){
				if(get(i+dx[k],j+dy[k])<a[i][j]){
					norm[i][j]=min(norm[i][j],a[i][j]-get(i+dx[k],j+dy[k]));
					for(int v=0;v<4;v++){
						if(v==k)continue;
						dir[v][i][j]=min(dir[v][i][j],a[i][j]-get(i+dx[k],j+dy[k]));
					}
				}
			}
			dbg(a[i][j],norm[i][j]);
		}
	}
	dbg("HI");
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			psa[i][j]=norm[i][j];
			if(i)
				psa[i][j]+=psa[i-1][j];
			for(int k=0;k<4;k++){
				ppp[k][i][j]=dir[k][i][j];
				if(i)
					ppp[k][i][j]+=ppp[k][i-1][j];
			}
		}
	}
	function<int(int,int,int)>sum=[&](int v,int l,int r){
		if(r<l)return 0ll;
		return psa[r][v]-(l?psa[l-1][v]:0ll);
	};
	// this is 4 directions
	preprocess();
	sparseTable<int>mintree(n,m);
	sparseTable<int>maxtree(n,m);
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			mintree.upd(i,j,a[i][j]);
			maxtree.upd(i,j,-a[i][j]);
		}
	}
	mintree.build();
	maxtree.build();
	int ans=0ll;
	function<int(int,int,int,int)>ssum=[&](int x,int y,int l,int r){
		if(r<l)return 0ll;
		return ppp[x][r][y]-(l?ppp[x][l-1][y]:0ll);
	};
	function<int(int,int,vector<int>)>best=[&](int i,int j,vector<int>d){
		int ans=a[i][j];
		for(int k:d){
			if(get(i+dx[k],j+dy[k])<a[i][j]){
				ans=min(ans,a[i][j]-get(i+dx[k],j+dy[k]));
			}
		}
		return ans;
	};
	// do all of length 1 here
	{
		int hori=0;
		for(int i=0;i<n;i++){
			// all paths of length n
			int s=0; int up=1; int lst=0;
			for(int j=0;j<m;j++){
				int v=a[i][j];
				if(up and v>lst){ }
				else if(!up and v<lst){ }
				else if(up and v<lst){
					hori+=(j-s)*(j-s+1ll)/2;
					hori-=(j-s); s=j-1; up=0;
				}
				else if(!up and v>lst){
					hori+=(j-s)*(j-s+1ll)/2;
					hori-=(j-s); s=j-1; up=1;
				}
				lst=v;
			}
			hori+=(m-s)*(m-s+1ll)/2;
			hori-=(m-s);
		}
		ans+=n*m;
		ans+=hori;
		int vert=0;
		for(int i=0;i<m;i++){
			// all paths of length n
			int s=0; int up=1; int lst=0;
			for(int j=0;j<n;j++){
				int v=a[j][i];
				if(up and v>lst){ }
				if(!up and v<lst){ }
				if(up and v<lst){
					vert+=(j-s)*(j-s+1ll)/2;
					vert-=(j-s); s=j-1; up=0;
				}
				if(!up and v>lst){
					vert+=(j-s)*(j-s+1ll)/2;
					vert-=(j-s); s=j-1; up=1;
				}
				lst=v;
			}
			vert+=(n-s)*(n-s+1ll)/2;
			vert-=(n-s);
		}
		ans+=vert;
		dbg(hori,vert);
	}
	dbg(ans);
	dbg(best(1,1,{0,3}));

	// do all with sides >=2 here
	for(int l=0;l<n;l++){
		for(int r=l;r<n;r++){
			// [l,r] is one dimension
			// now calculate all values
			vector<int>s(m),ll(m),rr(m),ps(m);
			if(r-l+1>=2){
				dbg(l,r,a[0],a[1]);
				for(int i=0;i<m;i++){ s[i]=sum(i,l+1,r-1); }
				for(int i=0;i<m;i++){
					s[i]+=dir[1][r][i];
					s[i]+=dir[0][l][i];
					ll[i]=ssum(2,i,l+1,r-1)+best(l,i,{1,3})+best(r,i,{0,3});
					rr[i]=ssum(3,i,l+1,r-1)+best(l,i,{1,2})+best(r,i,{0,2});
				}
				for(int i=0;i<m;i++){
					ps[i]=s[i];
					if(i)ps[i]+=ps[i-1];
				}
				dbg(s,ll,rr);
				// s in middle special case corners
				// left is 2, right is 3
				for(int x=0;x<m;x++){
					for(int y=x+1;y<m;y++){
						// ll[x]+rr[y]+s for the things in between
						int val=ps[y-1]-ps[x]+ll[x]+rr[y];
						int v=-maxtree.query(l,r,x,y);
						dbg(x,y,val,v);
						if(v==val){
							ans++;
						}
					}
				}

			}else{

			}
		}
	}
	cout<<ans<<"\n";
}
#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...