[CSP-S Simulation Test]: Simple section (partition)

Title Description

Given a length of n-$ $ $ A $ sequence and the constant $ k $, $ sequence numbered starting from $ 1.
Referred
$$ f (l, t) = \ sum \ limits_ {i = l} ^ ra_i- \ max \ limits_ {i = l} ^ r \ {a_i \} $$
positive integer legal requirements of $ (l, R & lt number) $ satisfy $ 1 \ leqslant l <r \ leqslant n $, and $ k | f (l, r ) $.


Input Format

The first line of two positive integers n-$ $ and $ k $.
The second line contains n-$ $ positive integer, the $ I $ positive integer $ a_i $.


Output Format

Line a positive integer representing the answer.


Sample

Sample input 1:

4 3
1 2 3 4

Sample output 1:

3

Sample input 2:

4 2
4 4 7 4

Sample Output 2:

6


Data range and tips

For $ 30 \% $ data, $ n \ leqslant 3,000 $;
for additional $ 20 \% $ data series $ A $ is randomly generated;
for $ 100 \% $ data, $ 1 \ leqslant n \ leqslant 3 \ times { 10} ^ 5,1 \ leqslant k \ leqslant {10} ^ 6,1 \ leqslant a_i \ leqslant {10} ^ 9 $.


answer

Consider divide and conquer, but I play with positive solutions are not the same.

$ Solve (l, r) on behalf of the endpoint are about $ $ [l, r] $ interval between legitimate number.

Clearly, we certainly can not turn enumerate each endpoint, so the time complexity is $ \ Theta (n ^ 2) $, so we consider optimization.

We can refer to enumerate one side, and then calculate the answer to this side when dealing with the other side.

Time complexity: $ \ Theta (n \ log n) $.

Desired points: $ 100 $ points.

The actual sub-: $ 100 $ points.


Code time

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[300001];
int s[300001];
int maxn[300001],pos[300001];
int t1[10000001],t2[10000001];
long long ans;
void wzc(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	int flag1=1,flag2=mid+1,mx=0;
	s[0]=s[mid]=maxn[0]=0;
	for(int i=mid+1;i<=r;i++)
	{
		if(a[i]>a[maxn[maxn[0]]])maxn[++maxn[0]]=i;
		s[i]=(s[i-1]+a[i])%k;
		t1[(s[i]-a[maxn[maxn[0]]]%k+k)%k]++;
		pos[i]=maxn[maxn[0]];
	}
	maxn[maxn[0]+1]=r+1;
	for(int i=mid;i>=l;i--)
	{
		s[0]=(s[0]+a[i])%k;
		mx=max(mx,a[i]);
		while(flag1<=maxn[0]&&a[maxn[flag1]]<=mx)flag1++;
		while(flag2<maxn[flag1])
		{
			t1[(s[flag2]-a[pos[flag2]]%k+k)%k]--;
			t2[s[flag2++]]++;
		}
		if(flag1<=maxn[0])ans+=t1[(k-s[0])%k];
		ans+=t2[(mx%k-s[0]+k)%k];
	}
	for(int i=mid+1;i<flag2;i++)t2[s[i]]--;
	for(int i=flag2;i<=r;i++)t1[(s[i]-a[pos[i]]%k+k)%k]--;
	wzc(l,mid);
	wzc(mid+1,r);
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	wzc(1,n);
	printf("%lld",ans);
	return 0;
}

rp ++

Guess you like

Origin www.cnblogs.com/wzc521/p/11494378.html