[CSP-S模拟测试]:慢无止境的八月(乱搞)

题目传送门(内部题102)


输入格式

  第一行三个正整数$n,k,q$,分别表示数列长度,操作长度和修改个数。
  第二行$n$个数,表示给出的终止数列。
  接下来$q$行,每行两个数$pos,dx$,表示将$a[pos]$加上$dx$,注意$dx$可能是负数。


输出格式

  输出共有$q+1$行,分别是初始时和每次修改后的答案。如果凉宫可以取胜,输出$Yes$,否则输出$No$。


样例

样例输入:

5 2 5
1 1 1 2 1
3 −1
1 −1
3 1
3 1
1 −1

样例输出:

Yes
No
No
No
Yes
No


数据范围与提示

样例解释:

  初始时,可以通过对$[1,2],[3,4],[4,5]$依次做$+1$操作得到;四次操作后,数列变为$[0,1,2,2,1]$,可以通过对$[2,3],[3,4],[4,5]$做$+1$操作得到。

数据范围:

  对于$10\%$的数据,满足$n=1,q=0$。
  对于$20\%$的数据,满足$n\leqslant 5,q=10$。
  对于$30\%$的数据,满足$n\leqslant 18,q=10$。
  对于$50\%$的数据,满足$n\leqslant 2,000,q\leqslant 2,000$。
  对于$70\%$的数据,满足$n\leqslant 100,000,q\leqslant 100,000$。
  对于$100\%$的数据,满足$k\leqslant n\leqslant 2\times 10^6,q\leqslant 2\times 10^6$,保证任何时候,$|a[i]|,|dx|\leqslant 10^9$。


题解

今晚是乱(mei)搞(lian)专题!

首先,如果整个区间和不是$k$的倍数的话一定是$No$,然后我就发现大样例中$2000$组询问只有$4$个是$k$的倍数。

于是$n^2$暴力$+$剪枝直接$AC$。

时间复杂度:$\Theta(\omega n)$(其中$\omega$为询问中区间和是$k$的倍数的个数)。

期望得分:$50$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,k,q;
long long sum;
int a[2000010],b[2000010],s[2000010],sss;
int main()
{
	scanf("%d%d%d",&n,&k,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	if(!k)
	{
		q++;
		while(q--)puts("No");
		return 0;
	}
	if(sum%k){puts("No");goto nxt3;}
	sss=0;
	for(int i=1;i<=n-k+1;i++)
	{
		sss+=s[i];
		b[i]+=a[i]-sss;
		sss+=b[i];
		s[i+k]-=b[i];
		b[i]=0;
	}
	for(int i=n-k+2;i<=n;i++)
	{
		sss+=s[i];
		b[i]+=a[i]-sss;
		if(b[i]!=0){puts("No");goto nxt1;}
	}
	puts("Yes");
	nxt1:for(int i=1;i<=n;i++)b[i]=s[i]=0;
	nxt3:;
	while(q--)
	{
		int pos,dx;
		scanf("%d%d",&pos,&dx);
		sum+=dx;a[pos]+=dx;
		if(sum%k){puts("No");goto nxt4;}
		sss=0;
		for(int i=1;i<=n-k+1;i++)
		{
			sss+=s[i];
			b[i]+=a[i]-sss;
			sss+=b[i];
			s[i+k]-=b[i];
			b[i]=0;
		}
		for(int i=n-k+2;i<=n;i++)
		{
			sss+=s[i];
			b[i]+=a[i]-sss;
			if(b[i]!=0){puts("No");goto nxt2;}
		}
		puts("Yes");
		nxt2:for(int i=1;i<=n;i++)b[i]=s[i]=0;
		nxt4:;
	}
	return 0;
}

rp++

猜你喜欢

转载自www.cnblogs.com/wzc521/p/11767443.html