记录编号 516871 评测结果 AAAAAAAAAA
题目名称 [HZOI 2015] 偏序++ 最终得分 100
用户昵称 Gravatarytxytx 是否通过 通过
代码语言 C++ 运行时间 7.299 s
提交时间 2018-10-26 16:57:02 内存使用 9.47 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>

int n,m;
const int inf=1<<30;

namespace Kd_tree{
	int nowD;

	struct node{
		int mini[7],maxi[7];
		int size,L,R;
	}T[100000];
	int tot,root;

	struct _node{
		int W[7];
	}U[100000];
	inline bool cmp(_node A,_node B){return A.W[nowD]<B.W[nowD];}

	inline double Pow(double k){return k*k;}

	int calc(int L,int R){
		double aver[7];
		double sq[7];
		for (int i=0;i<7;i++) aver[i]=sq[i]=0;
		for (int i=L;i<=R;i++)
			for (int j=0;j<m;j++) aver[j]+=U[i].W[j];
		for (int i=0;i<m;i++) aver[i]/=(R-L+1);
		for (int i=L;i<=R;i++)
			for (int j=0;j<m;j++) sq[j]+=Pow(U[i].W[j]-aver[j]);
		int maxi=0;
		for (int i=1;i<m;i++) if (sq[i]>sq[maxi]) maxi=i;
		return maxi;
	}

	void update(int now){
		if (!T[now].L&&!T[now].R) return;
		for (int i=0;i<m;i++){
			T[now].maxi[i]=-inf;
			T[now].mini[i]=inf;
		}
		T[now].size=0;
		if (T[now].L){
			for (int i=0;i<m;i++){
				T[now].mini[i]=std::min(T[now].mini[i],T[T[now].L].mini[i]);
				T[now].maxi[i]=std::max(T[now].maxi[i],T[T[now].L].maxi[i]);
			}
			T[now].size+=T[T[now].L].size;
		}
		if (T[now].R){
			for (int i=0;i<m;i++){
				T[now].mini[i]=std::min(T[now].mini[i],T[T[now].R].mini[i]);
				T[now].maxi[i]=std::max(T[now].maxi[i],T[T[now].R].maxi[i]);
			}
			T[now].size+=T[T[now].R].size;
		}
	}

	void build(int &now,int L,int R){
		now=++tot;
		if (L==R){
			for (int i=0;i<m;i++) T[now].mini[i]=T[now].maxi[i]=U[L].W[i];
			T[now].size=1;
			return;
		}
		nowD=calc(L,R);
		int mdl=(L+R)>>1;
		std::nth_element(U+L,U+mdl,U+R+1,cmp);
		build(T[now].L,L,mdl);
		build(T[now].R,mdl+1,R);
		update(now);
	}

	int query(int now,_node P){
		for (int i=0;i<m;i++) if (T[now].mini[i]>P.W[i]) return 0;
		bool rt=true;
		for (int i=0;i<m;i++) if (T[now].maxi[i]>P.W[i]){rt=false;break;}
		if (rt) return T[now].size;
		return query(T[now].L,P)+query(T[now].R,P);
	}
}

int ans;

int main(){
	freopen("partial_order_plus.in","r",stdin);
	freopen("partial_order_plus.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int j=0;j<m;j++)
		for (int i=1;i<=n;i++)
			scanf("%d",&Kd_tree::U[i].W[j]),Kd_tree::U[i].W[m]=i;
	m++;
	Kd_tree::build(Kd_tree::root,1,n);
	for (int i=1;i<=n;i++)
		for (int j=0;j<m;j++)
			Kd_tree::U[i].W[j]--;
	for (int i=1;i<=n;i++) ans+=Kd_tree::query(Kd_tree::root,Kd_tree::U[i]);
	printf("%d\n",ans);
}