喵哈哈村的嘟嘟熊魔法(四)(set+对组)

来源:互联网 发布:大数据的优缺点 编辑:程序博客网 时间:2024/05/17 03:12

喵哈哈村的嘟嘟熊魔法(4)

发布时间: 2017年3月5日 16:01   最后更新: 2017年3月5日 16:04   时间限制: 1000ms   内存限制: 128M

百度是喵哈哈村的赞助商,所以百度派出了嘟嘟熊给大家展现魔法:

“抽刀断水水更流,举杯消愁愁更愁。”

只见刹那间,嘟嘟熊就从兜里面掏出了一堆数字,这一堆数字仿佛有了生命,不停的在空气中跃动。

这些数字排成一排。

嘟嘟熊又从兜里面拿出了三把大刀,欲将这些数字斩断,连续三刀斩成四节,使得每一节的和都一样,且每一节的长度至少大于0。

比如数组A={2,5,1,1,1,1,4,1,7,3,7},就可以把下标为2,7,9的斩断,就变成了{2,5},{1,1,1,4},{7},{7},每一节的和都一样。

但是对于数组A={10,2,11,13,1,1,1,1,1},就不存在可以使得四节的和相同的方案。

本题包含若干组测试数据。
第一行一个n,表示有n个数字。
第二行n个整数a[i]。

保证 1<=n<=100000,-100000<=a[i]<=100000

如果可行的话,输出Yes,否则输出No

 复制
112 5 1 1 1 1 4 1 7 3 7910 2 11 13 1 1 1 1 1
YesNo


题目:http://qscoj.cn/problem/28/

题解:http://www.cnblogs.com/qscqesze/p/6505271.html


方法:

枚举中间的切点mid,然后判断左右两边是否都存在一个切点l,r使得正好平分

对于切点l,一定满足sum[l-1]==sum[mid-1]-sum[l],即sum[l-1]+sum[l]==sum[mid-1],其中sum[i]为前缀和

对于切点r,求一波后缀和sum'[],之后同理

如果对于某个当前中间切点mid,存在切点l和r,且sum[l-1]==sum'[r+1],那么就说明可以满足题目要求

开两个set,一个存对组pair(first, second),其中first表示sum[l-1]+sum[l](也就是sum[mid-1])

second表示s[l-1](也就是切割后每个小区间的和)

另一个存答案,ans[i]中的元素全部是左半部分能切出来的小区间和

那么在找右边的切点r的时候,只需要判断切出的小区间和是否在ans[i]中出现即可!


#include<stdio.h>#include<set>#include<algorithm>using namespace std;#define LL long longset<pair<LL, LL> > S;set<LL> ans[100005];LL n, a[100005], b[100005];int main(void){int i, ok;set<pair<LL, LL> >::iterator it;while(scanf("%lld", &n)!=EOF){for(i=1;i<=n;i++){scanf("%lld", &a[i]);b[i] = b[i-1]+a[i];ans[i].clear();}S.clear();for(i=4;i<=n;i++){S.insert(make_pair(b[i-2]+b[i-3], b[i-3]));it = S.lower_bound(make_pair(b[i-1], -10000000));while(it!=S.end() && (*it).first==b[i-1]){ans[i].insert((*it).second);it++;}}S.clear();ok = 0;for(i=n;i>=1;i--)b[i] = b[i+1]+a[i];for(i=n-3;i>=1;i--){S.insert(make_pair(b[i+2]+b[i+3], b[i+3]));it = S.lower_bound(make_pair(b[i+1], -10000000));while(it!=S.end() && (*it).first==b[i+1]){if(ans[i].find((*it).second)!=ans[i].end())ok = 1;it++;}}if(ok==1)printf("Yes\n");elseprintf("No\n");}}


阅读全文
1 0