LG-P6006 [USACO20JAN]Farmer John Solves 3SUM G 题解

The number of triples in the interval (satisfying ai + aj + ak = 0 ai + aj + ak = 0to i+a j+a k=0

(The fourth question of the first test of GZEZ New Year's Day)

in the specified range [ l , r ] [l, r][l,r ] ,ai + aj + ak = 0 ai + aj + ak = 0to i+a j+a k=The number of triples of 0 .


Ideas:

Preprocessing first, the time complexity is O ( n 2 ) O(n^2)O ( n2 ); query again, the time complexity isO ( 1 ) O(1)O ( 1 )

Preprocessing:

  1. After determining the numbers at both ends, the middle number = − a [ i ] − a [ j ] = -a[i]-a[j]=a[i]a [ j ] , and use buckets to count the number of each number, that is,dp [ i ] [ j ] = cnt [ m − a [ i ] − a [ j ] ] dp[i][j] = cnt[m - a[i] - a[j]]dp[i][j]=cnt[ma[i]a[j]] d p dp d p ​​is used to record the items that meet the conditions iniii tojjThe number of triples of j ; cnt cntc n t is used as a bucket to count the number of occurrences of each number).

  2. Remember to put cnt cnt outside the second level loopc n t The used part is cleared.

  3. dp[i][j] before dp[i][j]d p ​​[ i ] [ j ] counts withiii headed,jjj is the triple included at the end, if you want to get[ i , j ] [i,j][i,For all triples in j ] , use the following one-dimensional difference, that is:

    d p [ i ] [ j ] + = ( d p [ i + 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i + 1 ] [ j − 1 ] ) dp[i][j] += (dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1])dp[i][j]+=(dp[i+1][j]+dp[i][j1]dp[i+1][j1])

Inquire:

Enter l , rl,r directlyl,r , outputdp[l][r] dp[l][r]d p ​​[ l ] [ r ] is enough.


C o d e CodeCode

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

#define int long long 
int n, q;
const int m = 1000000;
const int maxn = 5005;
int a[maxn];
int dp[maxn][maxn];
int cnt[4000005];

signed main ()
{
    
    
	scanf ("%lld %lld", &n, &q);
	for (int i = 1; i <= n; i++)
	{
    
    
		scanf ("%lld", &a[i]);
	} 
	for (int i = 1; i <= n; i++)
	{
    
    
		for (int j = i + 1; j <= n; j++)
		{
    
    
			if (0 <= m - a[j] - a[i] and m - a[i] - a[j] <= 2 * m) dp[i][j] = cnt[m - a[i] - a[j]];
			cnt[a[j] + m]++;
		}
		for (int j = i + 1; j <= n; j++) cnt[a[j] + m]--;
	}
	for (int len = 3; len <= n; len++)
	for (int i = 1; i + len - 1 <= n; i++)
	{
    
    
		int j = i + len - 1;
		dp[i][j] += (dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]);
	}
	while (q--)
	{
    
    
		int l, r;
		scanf ("%lld %lld", &l, &r);
		printf ("%lld\n", dp[l][r]);
	}
	return 0;
}

If there are any mistakes in typesetting, please ask the administrator to be grateful! !

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324057583&siteId=291194637