[codeforces 1333C] Eugene and an array 寻找位置i所辖的最远位置

Codeforces Round #632 (Div. 2)   比赛人数12810

[codeforces 1333C]   Eugene and an array   寻找位置i所辖的最远位置

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1333/problem/C

Problem Lang Verdict Time Memory
C - Eugene and an array GNU C++17 Accepted 109 ms 5500 KB

造了两组数据,手工算法模拟如下

6
1 2 3 -5 2 3

12

数组a的脚标    1 2 3 4  5  6    
数组a的值      1 2 3 -5 2  3
数组a的前缀和  1 3 6  1 3  6

good subarrays如下
[1],[1,2],[1,2,3] 值1(位置1)  对应的右边界是  值3(位置3)
找到与位置1,相同前缀和(1)的位置4,位置4-1=3,即为位置3
   
[2],[2,3]         值2(位置2)  对应的右边界是  值3(位置3)
找到与位置2,相同前缀和(3)的位置5,位置5-1=4(下面数据会用到的位置4).
位置4与(上面位置1对应的边界)位置3找最小值,即为位置3

[3],[3,-5]        值3(位置3)  对应的右边界是  值-5(位置4)
找到与位置3,相同前缀和(6)的位置6,位置6-1=5(下面数据会用到的位置4).
位置5与(上面位置2对应的边界)位置4找最小值,即为位置4

[-5],[-5,2]       值-5(位置4)  对应的右边界是  值2(位置5)
找不到与位置4,相同前缀和(1)的位置,那就用默认的位置6(下面数据会用到的位置6).
位置6与(上面位置3对应的边界)位置5找最小值,即为位置5

[2],[2,3]         值2(位置5)  对应的右边界是  值3(位置6)
找不到与位置5,相同前缀和(3)的位置,那就用默认的位置6(下面数据会用到的位置6).
位置6与(上面位置4对应的边界)位置6找最小值,即为位置6

[3]               值3(位置6)  对应的右边界是  值3(位置6)
找不到与位置5,相同前缀和(6)的位置,那就用默认的位置6.
位置6与(上面位置4对应的边界)位置6找最小值,即为位置6

若觉得文字太罗嗦,请看数据生成过程
数组a的脚标    1 2 3 4  5  6    
数组a的值      1 2 3 -5 2  3
数组a的前缀和  1 3 6  1 3  6
right(初始化) 6 6 6  6  6  6


若觉得文字太罗嗦,请看数据生成过程
数组a的脚标                1 2 3 4  5  6    
数组a的值                  1 2 3 -5 2  3
数组a的前缀和              1 3 6  1 3  6
right(根据前缀和,进行生成) 3 4 5  6  6  6

若觉得文字太罗嗦,请看数据生成过程
数组a的脚标                1 2 3 4  5  6    
数组a的值                  1 2 3 -5 2  3
数组a的前缀和              1 3 6  1 3  6
right(逆向取最小值)        3 3 4  5  6  6

ans=(3-1+1)+(3-2+1)+(4-3+1)+(5-4+1)+(6-5+1)+(6-6+1)=12




  
8
1 2 0 3 4   0   5   6


9


数组a的脚标    1 2 3 4 5  6  7  8
数组a的值      1 2 0 3 4  0  5  6
数组a的前缀和  1 3 3 6 10 10 15 21


good subarrays如下
[1],[1,2] 值1(位置1)  对应的右边界是  值2(位置2)   
[2]       值2(位置2)  对应的右边界是  值2(位置2)
[0]       值0(位置3)  对应的右边界是  值2(位置2)
[3],[3,4] 值3(位置4)  对应的右边界是  值4(位置5)
[4]       值4(位置5)  对应的右边界是  值4(位置5)
[0]       值0(位置6)  对应的右边界是  值4(位置5)
[7],[7,8] 值7(位置7)  对应的右边界是  值8(位置8)
[8]       值8(位置8)  对应的右边界是  值8(位置8)



请看数据生成过程
数组a的脚标    1 2 3 4 5  6  7  8
数组a的值      1 2 0 3 4  0  5  6
数组a的前缀和  1 3 3 6 10 10 15 21
right(初始化) 8 8 8 8 8  8  8   8


请看数据生成过程
数组a的脚标                1 2 3 4 5  6  7  8
数组a的值                  1 2 0 3 4  0  5  6
数组a的前缀和              1 3 3 6 10 10 15 21
right(根据前缀和,进行生成) 8 2 8 8 5  8  8   8


请看数据生成过程
数组a的脚标                1 2 3 4 5  6  7  8
数组a的值                  1 2 0 3 4  0  5  6
数组a的前缀和              1 3 3 6 10 10 15 21
right(逆向取最小值)        2 2 2 5 5  5  8   8

注意right[i]=min(right[i],right[i-1]);right[i]=min(right[i],right[i+1])

ans=(2-1+1)+(2-2+1)+(2-3+1)+(5-4+1)+(5-5+1)+(8-7+1)+(8-8+1)=9




  

AC代码如下

#include <cstdio>
#include <algorithm>
#define maxn 200010
#define LL long long
using namespace std;
LL sum[maxn],ans;
struct node{
	int seq;//记录序列
	LL sum;//记录前缀和
}b[maxn];
int right[maxn];//right[i]代表位置i能管到的有效最远位置
int cmp(node a,node b){
	return a.sum==b.sum?a.seq<b.seq:a.sum<b.sum;
}
int main(){
	int i,a,n;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a),sum[i]=sum[i-1]+a;//前缀和计算
	for(i=0;i<=n;i++)b[i].seq=i,b[i].sum=sum[i];//i=0左边界设置
	sort(b+0,b+1+n,cmp);
	for(i=0;i<=n+1;i++)right[i]=n;//i=n+1右边界设置
	for(i=1;i<=n;i++)
		if(b[i].sum==b[i-1].sum)
			right[b[i-1].seq]=b[i].seq-1;//根据前缀和计算
	for(i=n;i>=1;i--)right[i]=min(right[i],right[i+1]),right[i]=min(right[i],right[i-1]);//逆向取最小值
	for(i=1;i<=n;i++)ans+=right[i]-i+1;
	printf("%lld\n",ans);
}
发布了660 篇原创文章 · 获赞 562 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/105408194