感觉自己在降智...

一开始写c想二分,二分半天也没二分出什么...最后是枚举.

想e的时候一直想偏序,我不知道正解是啥,最后写完我的想法刚好没时间了..当然还没调qwq

介绍下自己的想法,将方格的横坐标看成是时间,然后在维护时间的一个优先队列,假如现在的时间要大于优先队列对头的时间,那么对头就要去除,然后对于横坐标进行差分,只要从1开始到i的前缀和值是正数说明这个点被遍历过.细节就是一种颜色大于1的才有贡献,贡献是横纵坐标取min...肯定没这么复杂.待会看下正解.

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e6+5;
const int M=1e3+5;

struct sb{
	int x,y;
};

bool cmp(sb A,sb B)
{
	if(A.x==B.x)	return A.y<B.y;
	else			return A.x<B.x;
}

vector<sb>col[N];
bool vis[M][M];
int a[M][M];
vector<sb>num;
struct cnm{
	int x,y,time;
	friend bool operator <(cnm A,cnm B)
	{
		if(A.time==B.time)	return A.x<B.x; 
		else				return A.time>B.time; 
	}
};

priority_queue<cnm>Q;
vector<cnm>nm[M];
int b[M];

void run()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&a[i][j]);
			col[a[i][j]].push_back({i,j});
		}
	}
	for(int i=1;i<=1e6;i++)
	{
		//sort(col[i].begin(),col[i].end(),cmp);
		int mnx=1e9,mny=1e9,mxx=0,mxy=0;
		for(auto X:col[i])
		{
			mnx=min(mnx,X.x);
			mny=min(mny,X.y);
			mxx=max(mxx,X.x);
			mxy=max(mxy,X.y);
		}
		int sz=(int)col[i].size();
		if(sz>1)
		{
			//cout<<i<<' '<<col[i][0].y<<' '<<col[i][sz-1].y+1<<'\n';
			nm[mnx].push_back({mny,mxy+1,mxx+1});
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		while(Q.size())
		{
			auto y=Q.top();
			if(y.time<=i)
			{
				b[y.x]--,b[y.y]++;
				Q.pop();
			}
			else
			{
				break;
			}
		}
		for(cnm y:nm[i])	 b[y.x]++,b[y.y]--,Q.push({y});
        //for(int j=1;j<=m;j++)    cout<<b[j]<<' ';puts("");
		int res=0;
		for(int j=1;j<=m;j++)
		{
			res+=b[j];
			if(res<=0)	ans++;
		}
	}
	cout<<ans<<'\n';
}

int main()
{
	//debug();
	int T=1;
	//scanf("%d",&T);
	while(T--)	run(); 
	return 0;
}
/*

*/