QOJ.ac

QOJ

ID提交记录ID题目HackerOwner结果提交时间测评时间
#1046#666837#21696. 【NOIP Round #3】数圈圈max666dong123xiangqizhenSuccess!2024-10-22 20:19:422024-10-23 22:28:21

详细

Extra Test:

Time Limit Exceeded

input:

2000 2000
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu...

output:


result:


ID题目提交者结果用时内存语言文件大小提交时间测评时间
#666837#21696. 【NOIP Round #3】数圈圈xiangqizhen97 1503ms909452kbC++148.6kb2024-10-22 20:09:352024-10-23 22:49:20

answer

#include<bits/stdc++.h>
#define int long long
#define f(i,j,n) for(long long i=j;i<=n;i++)
#define updmax(a,b) a=max(a,b)
#define updmin(a,b) a=min(a,b)
#define pb push_back
#define XQZ
using namespace std;
int n,m;
const int S=2010*2;
const int N=2010;
char mp[2010][2010];
struct abc{
	int u,d,l,r;
	int tgv=0,tg_re=0,sum=0;
}Tree[N*N*4];
#define zs(k) k<<2
#define ys(k) k<<2|1
#define zx(k) k<<2|2
#define yx(k) k<<2|3
#define midy ((Tree[k].u+Tree[k].d)>>1)
#define midx ((Tree[k].l+Tree[k].r)>>1)
#define uns(k) ((k)>=(N*N*4-1)||Tree[k].u>Tree[k].d||Tree[k].l>Tree[k].r)
#define ist(k,up,down,lft,rght) (Tree[k].d>=up&&Tree[k].u<=down&&Tree[k].l<=rght&&Tree[k].r>=lft)
#define ctn(k,up,down,lft,rght) (Tree[k].d<=down&&Tree[k].u>=up&&Tree[k].l>=lft&&Tree[k].r<=rght)
//#define uist(a) (!ist(a,up,down,lft,rght))
inline void build(int k,int up,int down,int lft,int rght){
	Tree[k].u=up,Tree[k].d=down,Tree[k].l=lft,Tree[k].r=rght;
//		cout<<k<<"->"<<up<<" "<<down<<" "<<lft<<" "<<rght<<endl;
	if(uns(k))return;
	if(up==down&&lft==rght){Tree[k].sum=0;return;}
	int ms=(up+down)>>1,ls=(lft+rght)>>1;
	build(zs(k),up,ms,lft,ls);
	build(ys(k),up,ms,ls+1,rght);
	build(zx(k),ms+1,down,lft,ls);
	build(yx(k),ms+1,down,ls+1,rght);
}
inline void push(int k){Tree[k].sum=0,Tree[k].tgv=0,Tree[k].tg_re=1;}
inline void upd(int k,int v){
	if(Tree[k].tg_re){
		f(j,0,3)if(!uns(k<<2|j))push(k<<2|j);
		Tree[k].tg_re=0;
	}
	Tree[k].sum+=(Tree[k].r-Tree[k].l+1)*(Tree[k].d-Tree[k].u+1)*v,Tree[k].tgv+=v;
}
inline void pushdown(int k){
//	cout<<"pushdown:"<<k<<" "<<Tree[k].tg_re<<" "<<Tree[k].tgv<<" "<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
	if(Tree[k].tgv){
		f(j,0,3)if(!uns(k<<2|j))upd(k<<2|j,Tree[k].tgv);
		Tree[k].tgv=0;
	}
	if(Tree[k].tg_re){
		f(j,0,3)if(!uns(k<<2|j))push(k<<2|j);
		Tree[k].tg_re=0;
	}
}
inline void pushup(int k){Tree[k].sum=0;f(j,0,3)if(!uns(k<<2|j))Tree[k].sum+=Tree[k<<2|j].sum;}
inline void modify(int k,int up,int down,int lft,int rght,int v){
	if(uns(k))return;
	if(!ist(k,up,down,lft,rght))return;
//		cout<<k<<":";cout<<up<<" "<<down<<" "<<lft<<" "<<rght<<endl;
	if(ctn(k,up,down,lft,rght)){
//			cout<<"modi"<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
		upd(k,v);return;
	}
	
//		cout<<k<<":";cout<<up<<" "<<down<<" "<<lft<<" "<<rght<<endl;
//	if(ctn(k,up,down,lft,rght)){
////			cout<<"modi"<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
//		upd(k,v);return;
//	}
	pushdown(k);
////	Tree[k].sum=0;
	if(lft<=midx){
		if(up<=midy){
			Tree[k].sum-=Tree[zs(k)].sum;
			modify(zs(k),up,down,lft,rght,v);
			Tree[k].sum+=Tree[zs(k)].sum;
		}
		if(down>midy&&Tree[k].u!=Tree[k].d){
			Tree[k].sum-=Tree[zx(k)].sum;
			modify(zx(k),up,down,lft,rght,v);
			Tree[k].sum+=Tree[zx(k)].sum;
		}
	}
	if(rght>midx&&Tree[k].l!=Tree[k].r){
		if(up<=midy){
			Tree[k].sum-=Tree[ys(k)].sum;
			modify(ys(k),up,down,lft,rght,v);
			Tree[k].sum+=Tree[ys(k)].sum;
		}
		if(down>midy&&Tree[k].u!=Tree[k].d){
			Tree[k].sum-=Tree[yx(k)].sum;
			modify(yx(k),up,down,lft,rght,v);
			Tree[k].sum+=Tree[yx(k)].sum;
		}
	}
//	pushdown(k);
//	f(j,0,3)modify(k<<2|j,up,down,lft,rght,v);
//	pushup(k);
}
inline void modi_re(int k,int up,int down,int lft,int rght){
//	if(uns(k))return;
////	cout<<Tree[17].tg_re<<endl;
//	if(!ist(k,up,down,lft,rght))return;
	if(ctn(k,up,down,lft,rght)){
//			cout<<"re "<<k<<":"<<Tree[k].sum<<"->"<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
		push(k);return;
	}
//	cout<<" to to ->re "<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
	pushdown(k);
//	Tree[k].sum=0;
	if(lft<=midx){
		if(up<=midy){
			Tree[k].sum-=Tree[zs(k)].sum;
			modi_re(zs(k),up,down,lft,rght);
			Tree[k].sum+=Tree[zs(k)].sum;
		}
		if(down>midy&&Tree[k].u!=Tree[k].d){
			Tree[k].sum-=Tree[zx(k)].sum;
			modi_re(zx(k),up,down,lft,rght);
			Tree[k].sum+=Tree[zx(k)].sum;
		}
	}
	if(rght>midx&&Tree[k].l!=Tree[k].r){
		if(up<=midy){
			Tree[k].sum-=Tree[ys(k)].sum;
			modi_re(ys(k),up,down,lft,rght);
			Tree[k].sum+=Tree[ys(k)].sum;
		}
		if(down>midy&&Tree[k].u!=Tree[k].d){
			Tree[k].sum-=Tree[yx(k)].sum;
			modi_re(yx(k),up,down,lft,rght);
			Tree[k].sum+=Tree[yx(k)].sum;
		}
	}
//	f(j,0,3)if(!uns(k<<2|j))modi_re(k<<2|j,up,down,lft,rght);
//	modi_re(zs(k),up,down,lft,rght);
////	f(i,0,3)modi_re(k<<2|i,up,down,lft,rght);
//	if(Tree[k].l!=Tree[k].r){
//		modi_re(ys(k),up,down,lft,rght);
//		if(Tree[k].d!=Tree[k].u)modi_re(yx(k),up,down,lft,rght);
//	}if(Tree[k].d!=Tree[k].u)modi_re(zx(k),up,down,lft,rght);
//	pushup(k);
//	cout<<" to to ->re "<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<" "<<Tree[k].sum<<endl;
}
inline int ask(int k,int up,int down,int lft,int rght){
	if(uns(k))return 0;
	if(!ist(k,up,down,lft,rght))return 0;
	if(ctn(k,up,down,lft,rght)){
//			cout<<Tree[k].u<<" "<<Tree[k].d<<" "<<Tree[k].l<<" "<<Tree[k].r<<endl;
		return Tree[k].sum;
	}
	pushdown(k);
	int sc=0;
	f(j,0,3)sc+=ask(k<<2|j,up,down,lft,rght);return sc;
}
int dp[2010];
namespace sss{
	int dp[2010][2010];
//bool bs[2010][2010];
	bitset<2010> bs[2010];
	bitset<2010> bsp[2010];
//bool vv[2010];
	void gs(){
//	cin>>n>>m;
//	f(i,1,n)f(j,1,m)cout<<mp[i][j];
//		cout<<"!\n";
		int ans=0;
		f(i,1,n){
//			cout<<i<<endl;
//		for(int l=1;l<=m;l++)for(int r=l;r<=m;r++)dp[i&1][l][r]=((i>1)&(mp[i-1][l]==mp[i][l])&(mp[i-1][r]==mp[i][r]))*dp[i&1^1][l][r];
//		for(int k=1;k<=m;k++)if(i<=1||mp[i-1][k]!=mp[i][k])f(s,1,m)dp[s][k]=dp[k][s]=0;
			for(int l=1;l<=m;l++){
				if(!(i>1&&mp[i-1][l]==mp[i][l])){bs[l].reset();}
				if(!(i>1&&mp[i-1][l]==mp[i][l])){bsp[l].reset();}
			}
			
//		for(int l=1;l<=m;l++)vv[l]=bs[l];
			int lst=0;
//		cout<<"==========="<<i<<":\n";
//		f(l,1,m)cout<<bs[l]<<" ";cout<<endl;
			for(int k=1;k<=m;k++){
				if(mp[i][k]!=mp[i][k-1]){
					lst=k;
				}
//			int sp=bs[k];
				for(int j=k-1;j>=lst;j--){
//				sp&=bs[j];
					if(!bs[j][k]||!bsp[k][j]){
//					cout<<"in:"<<j<<" "<<k<<" "<<bs[j]<<" "<<bs[k]<<endl;
						dp[j][k]=1;
						bs[j][k]=1;
						bsp[k][j]=1;
						continue;
					}
//				cout<<"+"<<j<<" "<<k<<" "<<dp[j][k]<<endl;
					ans+=dp[j][k];
					dp[j][k]++;
				}
			}
//		f(j,1,m)bs[j]=vv[j];
		}
		cout<<ans<<endl;
	}
}
int cnt=0;
const int base=10000;
inline void gs(){
//	cin>>n>>m;
	scanf("%lld%lld",&n,&m);
	char s=0;
	int cnt=0;
	f(i,1,n)f(j,1,m){
		char c=getchar();
		while(c>'z'||c<'a')c=getchar();
		mp[i][j]=c;
		if(s==0)s=mp[i][j];
		if(s!=mp[i][j])s=18;
		cnt+=(i==1||mp[i][j]!=mp[i-1][j]);
	}
	if(s!=18){
		cout<<(n*(n-1)/2*m*(m-1)/2)<<endl;return;
	}
//	sss::gs();return;
//	cout<<cnt<<endl;
	if(cnt>=base){sss::gs();return;}
	build(1,1,m,1,m);
//	Tree[1].modify(1,3,4,1);
//	Tree[1].modi_re(1,4,5);
//	cout<<Tree[1].ask(1,3,4)<<endl;
//	modify(1,1,5,1,1,5);
//	cout<<"[["<<ask(1,1,5,1,5)<<endl;
//	modi_re(1,2,2,1,5);
//	cout<<"[["<<ask(1,1,5,1,5)<<endl;
//	modi_re(1,1,5,2,2);
//	cout<<"[["<<ask(1,1,5,1,5)<<endl;
//	f(i,1,n)f(j,1,m)cout<<mp[i][j];
	int ans=0;
	f(i,1,n){
//		if(i%10==0)cout<<i<<" "<<cnt<<endl;
//		cout<<":::"<<ask(1,1,m,1,m)<<endl;
		int lst=1;
		f(l,1,m){
			if(i<=1||mp[i][l]!=mp[i-1][l]){
				dp[l]=0;
//				continue;
				++cnt;
			}else{
//				if(++cnt%100==0)cout<<"::"<<cnt<<endl;
//				cout<<"["<<l<<" "<<l<<" "<<1<<" "<<m<<"]\n";
//				cout<<"?";
				if(lst<=l-1){
//					cout<<"~"<<lst<<" "<<l-1<<endl;
					modi_re(1,lst,l-1,1,m);
//				if(++cnt%100==0)cout<<"::"<<cnt<<endl;
//				cout<<ask(1,1,5,4,4)<<endl;
//				cout<<ask(1,1,m,1,m)<<endl;
//				cout<<"["<<1<<" "<<m<<" "<<l<<" "<<l<<"]\n";
//				++cnt;
					modi_re(1,1,m,lst,l-1);
				}
				lst=l+1;
//				if(cnt>=1000000){exit(0);}
//				cout<<ask(1,1,5,4,4)<<endl;
//				cout<<ask(1,1,m,1,m)<<endl;
			}
		}
//		continue;
		if(lst<=m){
//			cout<<"--"<<lst<<" "<<m<<endl;
			modi_re(1,lst,m,1,m);
			modi_re(1,1,m,lst,m);
		}
//		continue;
//		f(j,1,m)cout<<dp[j]<<" ";cout<<endl;
//		cout<<ask(1,1,m,1,m)<<endl;
		lst=0;
		int sum=0;
		for(int k=1;k<=m;k++){
			if(mp[i][k]!=mp[i][k-1]){
				ans+=(ask(1,lst,k-1,lst,k-1)-sum)/2;
				modify(1,lst,k-1,lst,k-1,1);
				lst=k;
				sum=0;
			}
			sum+=dp[k];
		}
//		cout<<"[[]"<<lst<<" "<<m<<" "<<lst<<" "<<m<<endl;
		ans+=(ask(1,lst,m,lst,m)-sum)/2;
		modify(1,lst,m,lst,m,1);
//		cout<<"----------->"[<<i<<":"<<ans<<endl;
//		ans+=sum;
		f(k,1,m)dp[k]++;
	}
	cout<<ans<<endl;
}
signed main(){
//#ifndef XQZ
//	freopen("jx4.out","r",stdin);	
//	freopen("circle.out","w",stdout);
//#endif
#ifdef NXD
	int t=0;cin>>t;while(t--)
#endif
		gs();
	return 0;
}