ZZULIOJ 1917: E(序列的价值,思维,vector)

题目:http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1917

1917: E

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 135   Solved: 28

Submit Status Web Board

Description

晴天有非常严重的选择恐惧症,每次吃饭前他都在纠结到底吃什么。。今天又到了吃饭的时候了。

重光:我给你一个包含n个不同整数的序列a,如果它所有连续子序列的价值和是素数咱们就吃米,不然就吃面。

定义一个序列的价值为序列中所有元素的最小值。

晴天:这不是分分钟给你算出来。

嗯...十分钟过去了,晴天选择死亡。

这个任务就交给你啦。

算出所有连续子序列的价值和。

Input

第一行输入一个整数t,代表有t组测试数据。
每组数据第一行包含一个整数n,表示序列a的元素个数。
接下来一行包含n个整数,表示序列a。
0<=n<=50000,1<=ai<=50000。

Output

对于每组数据输出一个整数,表示序列a的所有连续子序列的价值和。

Sample Input

131 2 3

Sample Output

10

思路:

宇神说了,这是一类题型:就是求解子序列的价值。

变形就有好几类,如图:

回到题意,这个题目减小难度,毕竟没有重复的元素,没有重复的元素就能够用一个规律,

不知道是不是规律,应该是个小技巧,就是判断序列中含有当前元素的子序列个数



参考Code:

/*
	Name:http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1917
	Copyright:Shyazhut
	Author:WQS
	Date:2016-8-19 16:27:31
	Description:大一暑期比赛第三场,子序列价值的类型题目
*/

#include<stdio.h>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MYDD=1103+5e4;

vector<int> Vec;
vector<int>::iterator it;/*建立迭代器*/
int a[MYDD];
int pos[MYDD];/*记录元素a[]位置*/

int main() {
	int TT;
	scanf("%d",&TT);
	while(TT--) {
		int n;
		scanf("%d",&n);
		for(int j=1; j<=n; j++) {
			scanf("%d",&a[j]);
			pos[a[j]]=j;
		}

		LL ans=0;
		Vec.clear();
		sort(a+1,a+1+n);
		for(int j=1; j<=n; j++) {
			it=upper_bound(Vec.begin(),Vec.end(),pos[a[j]]);/*迭代器it接收的是指针*/

			/*在pos[]序列查找后四种情况的分析*/
			int L,R;/*统计pos[]位置左右元素个数*/
			if(it==Vec.end()) {/*没有找到比pos[]大的*/
				if(Vec.size()==0) {/*没有找到比pos[]小的*/
					L=pos[a[j]]-1;
					R=n-pos[a[j]];
				} else {/*此时pos[]在最后位置*/
					int p=it-Vec.begin()-1;
					L=pos[a[j]]-Vec[p]-1;
					R=n-pos[a[j]];
				}
			} else {/*注意两处找不到比pos[]小的语句不同*/
				if(Vec.begin()==it) { /*此时pos[]在第一位置*/
					L=pos[a[j]]-1;
					int p=it-Vec.begin();
					R=Vec[p]-pos[a[j]]-1;
				} else {
					int p=it-Vec.begin();
					L=pos[a[j]]-Vec[p-1]-1;
					R=Vec[p]-pos[a[j]]-1;
				}
			}

			ans=ans+(LL)((L+1)*(R+1)*a[j]);
			it=lower_bound(Vec.begin(),Vec.end(),pos[a[j]]);
			Vec.insert(it,pos[a[j]]);/*把pos[]插入到 it 之前*/
		}
		printf("%lld\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值