Official

E - Team Division Editorial by en_translator


For each \(i=1,2,\ldots, N-1\), let us consider how many ways are there to form teams so that team \(A\) and team \(B\) have \(i\) and \((N-i)\) players, respectively. The sought answer is their sum.

Each person \(j=1,2,\ldots, N\) falls into one of the following four groups:

  • Group \(1\): If \(L_j\leq i\leq R_j\) and \(L_j\leq (N-i)\leq R_j\) both hold, player \(j\) can belong to either team \(A\) or team \(B\).
  • Group \(2\): If \(L_j\leq i\leq R_j\) holds but \(L_j\leq (N-i)\leq R_j\) fails, player \(j\) can only belong to team \(A\).
  • Group \(3\): If \(L_j\leq i\leq R_j\) fails but \(L_j\leq (N-i)\leq R_j\) holds, player \(j\) can only belong to team \(B\).
  • Group \(4\): If neither \(L_j\leq i\leq R_j\) nor \(L_j\leq (N-i)\leq R_j\) holds, player \(j\) can belong to neither team \(A\) nor \(B\).

If at least one of the following conditions is satisfied, there is no way to satisfy the condition for this \(i\):

  • There are at least \((i+1)\) players of group \(2\).
  • There are at least \((N-i+1)\) players of group \(3\).
  • There is at least one player of group \(4\).

This is because every player must belong to either team, and team \(A\) and \(B\) must have exactly \(i\) and \((N-i)\) players, respectively.

Otherwise, if we denote by \(X_{i,1},X_{i,2},X_{i,3}\) the number of players in groups \(1,2,3\), respectively (where \(X_{i,1}+X_{i,2}+X_{i,3}=N\) because no player falls into group \(4\) by assumption), it is necessary and sufficient for team \(A\) to have, in addition to all players in group \(2\), \((i-X_{i,2})\) out of the \(X_{i,1}\) players in group \(1\); and for team \(B\) to have, in addition to those in group \(3\), the remaining \(X_{i,1}-(i-X_{i,2})=(N-i-X_{i,3})\) players in group \(1\). Therefore, the number of ways to satisfy the conditions is

\[ \binom{X_{i,1}}{i-X_{i,2}}=\frac{X_{i,1}!}{(i-X_{i,2})!~(N-i-X_{i,3})!}, \]

where \(\binom{n}{k}\) denotes a binomial coefficient.
As already mentioned, the answer is obtained as the sum of \(i=1,2,\ldots,N-1\) by taking its remainder.

\(X_{i,1}\), which is at most \(N\), can be computed in \(O(1)\) time by precomputing \(k!\) and its inverse modulo \(998244353\) for every \(k=0,1,\ldots,N\).

Also, naively finding \(X_{i,1}, X_{i,2}, X_{i,3}\) for each \(i\) costs a total of \(O(N^2)\) time, but if we find them in ascending order of \(i\), the group player \(j\) belongs to changes at most four times: \(i=L_j-1\to L_j\), \(R_j\to R_j+1\), \((N-R_j-1)\to(N-R_j)\), and \((N-L_j)\to (N-L_j+1)\). For each \(i\), by inspecting only the players whose groups are affected by \(i-1\to i\), they can be found in a total of \(O(N)\) time.

The precalculation costs \(O(N\log P)\) time (where \(P=998244353\) this time), and finding \(X_{i,1}, X_{i,2}, X_{i,3}\) and counting the divisions cost a total of \(O(N)\) time, so the problem can be solved in a total of \(O(N\log P)\) time.
Hence, the problem has been solved.

Sample code in C++:

#include <bits/stdc++.h>
#include <atcoder/modint>
using namespace std;
using namespace atcoder;

using mint = modint998244353;

#define N (int)3e+5
#define rep(i, n) for(int i = 0; i < n; ++i)

mint frac[N+1];

void pre_calc(void){
	frac[0]=mint(1);
	for(int i=1;i<=N;i++){
		frac[i]=frac[i-1]*mint(i);
	}
	return;
}

mint binom(int x,int y){
	if(x<0)return mint(0);
	if(y<0)return mint(0);
	if(y>x)return mint(0);
	return frac[x]*(frac[y].inv())*(frac[x-y].inv());
}

int main(void){
	int n;
	int l[N],r[N];
	int aok[N]={},bok[N]={};
	int m[2][2]={};
	vector<int>cand[N];
	mint ans=mint(0);
	cin>>n;
	rep(i,n){
		cin>>l[i]>>r[i];
		cand[l[i]].push_back(i);
		cand[r[i]+1].push_back(i);
		cand[n-l[i]+1].push_back(i);
		cand[n-r[i]].push_back(i);
	}
	m[0][0]=n;

	pre_calc();
	for(int i=1;i<=n-1;i++){
		int sz=cand[i].size();
		rep(j,sz){
			int z=cand[i][j];
			m[aok[z]][bok[z]]--;
			if((l[z]<=i)&&(i<=r[z]))aok[z]=1;
			else aok[z]=0;
			if((l[z]<=(n-i))&&((n-i)<=r[z]))bok[z]=1;
			else bok[z]=0;
			m[aok[z]][bok[z]]++;
		}
		if((m[0][0]==0)&&(m[1][0]<=i)&&(m[0][1]<=(n-i))){
			ans+=binom(m[1][1],i-m[1][0]);
		}
	}
	cout<<ans.val()<<endl;
}

posted:
last update: