题目:http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1917
1917: E
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 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;
}