最大连续子序和 (加强版?)
来源:互联网 发布:吴亦凡 扒皮 知乎 编辑:程序博客网 时间:2024/06/06 20:25
题目描述 Description
给你K个序列(编号从0到K-1),并且第i个序列有Ni个元素。然后将会有一个由(0~K-1)组成的字符串S=(s1,s2,...,sn)。如果si=p,
那么把第p个序列增加到这个大的序列上。
例如:
如果你有小的序列:
0.{1,2,3}
1.{-1,2,0}
2.{3,4,5,-6}
字符串S="1021",那么这个大的序列是{-1,2,0,1,2,3,3,4,5,-6,-1,2,0}
接下来,对于大的序列将会有M组询问如下:
Query(x, y) = Max{a[i] + a[i + 1] + ... + a[j] ; 1 <= x <= i <= j <= y <= len(大序列的长度)}.
输入描述 Input Description
第一行有两个整数K, M。
接下来K行,每行开始用一个整数Ni,表示小的序列的个数,接下来Ni个整数每个整数的绝对值范围不超过100,000 。
然后是有一个由(0~K-1)组成的字符串S。
接下来M行,每行两个整数x, y代表每组询问。(1 <= x <= y <= len(大序列的长度))。
输出描述 Output Description对于每组询问输出答案。
样例输入 Sample Input
3 3
3 1 -2 3
3 5 6 -7
4 2 0 6 8
0120
1 3
4 6
4 13
样例输出 Sample Output3 11 22
20%的数据中1<=K<=3,1<=M<=10,1<=Ni<=10,1<=S<=10;
40%的数据中1<=K<=10,1<=M<=1000,1<=Ni<=100,1<=S<=100;
60%的数据中1<=K<=10,1<=M<=10000,1<=Ni<=1000,1<=S<=1000;
100%的数据中1<=K<=10,1<=M<=100000,1<=Ni<=10000,1<=S<=100000;
传送门:http://codevs.cn/problem/2012/
题目大意:中文题,自己看咯。
题目分析:其实就是求给定区间内的最大子段和。只要写个裸的线段树,记录几个值就是啦。考虑到父区间的最大子段可能是左子区间内的最大段也可能是右区间内的又或者是跨过中间左右都有。那么我们只需要记录子区间的lmax,mmax,rmax。mmax是该区间的最大子段和,lmax是从左端点起得最大子段和,rmax同 lmax啦。然后合并到父区间就很简单啦。题目本来是很简单的,可是突然凑出个S串。其实只要再建一棵总树。总共k+1棵线段树就是辣。在询问的时候多个判断就是了。PS:好久没写线段树,那么快写出一个,又那么久没写题解了,就拿来凑一个了。代码风格有点丑,空间也不省,如果谁有更好的姿势,请一定要教我~#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node { int l,r;///左闭右开 long long ll,rr,lmax,mmax,rmax,sum;};char s[100010];int n[12],aa[100010],a[12][10100];long long ssum[100010];node f[12][100000],tree[1000000];void build_tree(int i,int g,int l,int r){ f[i][g].l=l;f[i][g].r=r; if (l+1>=r) { f[i][g].lmax=a[i][l];f[i][g].mmax=a[i][l]; f[i][g].rmax=a[i][l];f[i][g].sum=a[i][l]; return ; } build_tree(i,2*g,l,(l+r)/2); build_tree(i,2*g+1,(l+r)/2,r); f[i][g].lmax=max(f[i][2*g].lmax,f[i][2*g].sum+f[i][2*g+1].lmax); f[i][g].rmax=max(f[i][2*g+1].rmax,f[i][2*g+1].sum+f[i][2*g].rmax); f[i][g].sum=f[i][2*g].sum+f[i][2*g+1].sum; f[i][g].mmax=max(f[i][2*g].mmax,f[i][2*g+1].mmax); f[i][g].mmax=max(f[i][g].mmax,f[i][g].lmax); f[i][g].mmax=max(f[i][g].mmax,f[i][g].rmax); f[i][g].mmax=max(f[i][g].mmax,f[i][2*g].rmax+f[i][2*g+1].lmax);}void build_trees(int g,int l,int r){ tree[g].l=l;tree[g].r=r; if (l+1>=r) { tree[g].ll=ssum[l-1]+1;tree[g].rr=ssum[l]; tree[g].lmax=f[aa[l]][1].lmax;tree[g].rmax=f[aa[l]][1].rmax; tree[g].mmax=f[aa[l]][1].mmax;tree[g].sum=f[aa[l]][1].sum; return ; } build_trees(2*g,l,(l+r)/2); build_trees(2*g+1,(l+r)/2,r); tree[g].ll=tree[2*g].ll;tree[g].rr=tree[2*g+1].rr; tree[g].lmax=max(tree[2*g].lmax,tree[2*g].sum+tree[2*g+1].lmax); tree[g].rmax=max(tree[2*g+1].rmax,tree[2*g+1].sum+tree[2*g].rmax); tree[g].sum=tree[2*g].sum+tree[2*g+1].sum; tree[g].mmax=max(tree[2*g].mmax,tree[2*g+1].mmax); tree[g].mmax=max(tree[g].mmax,tree[g].lmax); tree[g].mmax=max(tree[g].mmax,tree[g].rmax); tree[g].mmax=max(tree[g].mmax,tree[2*g].rmax+tree[2*g+1].lmax);}node getmax(int i,int g,long long l,long long r){ node ret,lret,rret; if (f[i][g].l==l&&f[i][g].r-1==r) return f[i][g]; if (r<f[i][2*g].r) return getmax(i,2*g,l,r); else if (l>=f[i][2*g+1].l) return getmax(i,2*g+1,l,r); else { lret=getmax(i,2*g,l,f[i][2*g].r-1); rret=getmax(i,2*g+1,f[i][2*g+1].l,r); ret.lmax=max(lret.lmax,lret.sum+rret.lmax); ret.rmax=max(rret.rmax,rret.sum+lret.rmax); ret.mmax=max(lret.mmax,rret.mmax); ret.mmax=max(ret.mmax,ret.lmax); ret.mmax=max(ret.mmax,ret.rmax); ret.mmax=max(ret.mmax,lret.rmax+rret.lmax); return ret; }}node getmaxs(int g,long long l,long long r){ node ret,lret,rret; if (tree[g].ll==l&&tree[g].rr==r) return tree[g]; if (tree[g].l+1>=tree[g].r) return getmax(aa[tree[g].l],1,l-ssum[tree[g].l-1],r-ssum[tree[g].l-1]); if (r<=tree[2*g].rr) return getmaxs(2*g,l,r); else if (l>=tree[2*g+1].ll) return getmaxs(2*g+1,l,r); else { lret=getmaxs(2*g,l,tree[2*g].rr); rret=getmaxs(2*g+1,tree[2*g+1].ll,r); ret.lmax=max(lret.lmax,lret.sum+rret.lmax); ret.rmax=max(rret.rmax,rret.sum+lret.rmax); ret.mmax=max(lret.mmax,rret.mmax); ret.mmax=max(ret.mmax,ret.lmax); ret.mmax=max(ret.mmax,ret.rmax); ret.mmax=max(ret.mmax,lret.rmax+rret.lmax); return ret; }}int main(){ int i,j,k,m,len; node kk; long long x,y; scanf("%d%d", &k, &m); for (i=1;i<=k;i++) { scanf("%d", &n[i]); for (j=1;j<=n[i];j++) scanf("%d", &a[i][j]); } for (i=1;i<=k;i++) build_tree(i,1,1,n[i]+1); scanf("%s", &s);len=strlen(s);ssum[0]=0;for (i=0;i<len;i++) aa[i+1]=s[i]-'0'+1,ssum[i+1]=ssum[i]+n[aa[i+1]]; build_trees(1,1,len+1);while (m--) { scanf("%lld%lld", &x, &y); kk=getmaxs(1,x,y); printf("%lld ", kk.mmax);}return 0;}
- 最大连续子序和 (加强版?)
- HDU1244最大连续子字段和最终加强版
- 最大连续子序和
- C6-4 最大子数组和(加强版)
- hdu1003 最大连续子序和
- HDU-1003最大连续子序和
- HDU1003 最大连续子序和 DP
- hdu1003 最大连续子序和
- 连续子数组的最大和(java版)
- leetcode 最大子序列和(连续)
- 最大连续子序列和(小结)
- 最大连续子串和(DP)
- 最大连续子序列和(java)
- 最大连续子段和(hdu1003)
- 最大子数组和(最大子序列和 | 连续子数组最大和)
- 最大子数组和(最大子序列和 | 连续子数组最大和)(转)
- 最大连续子段和
- 最大连续子串和
- TIMER/COUNTER输入捕获与输出比较
- Java4Andriod 从零学起 ---learn7
- 乱弹java并发(三)-- CopyOnWriteArrayList和CopyOnWriteArraySet
- 初探NO.3—从头到尾聊聊贝叶斯的分类方法
- UVA 10487 Closest Sums(二分)
- 最大连续子序和 (加强版?)
- java.sql.SQLException:Invalid value for getInt()-'zhangsan'
- Let the Balloon Rise
- PHP HttpClient模拟登陆
- 新站必须经过的几个百度时期
- 在安卓service中启动相机
- (四十一)数据持久化的NSCoding实现 -实现普通对象的存取
- 面向对象-基础
- 【Android如何禁止横竖屏切换】