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:
-
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[m−a[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).
-
Remember to put cnt cnt outside the second level loopc n t The used part is cleared.
-
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][j−1]−dp[i+1][j−1])
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! !