Uva 1400 "Ray, Pass me the dishes!" (线段树 + 区间查询)
题意:
给顶一个长度为n的整数序列D,我们的任务是对m的询问做出回答
对于询问(a,b),需要找到两个下标x和y,是的 a <= x <= y <=b
并且Dx+...........Dy 尽量大. x,y尽量小
分析:
这题是做线段树比较好的一题,大白书上介绍的是维护了三个域,maxsub,maxpre,maxsuf
这里也可以只维护两个域,再最后再考虑跨区间的问题
这里没有update操作,但是需要注意的是PushUp和Query.
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MID ( l + r ) >> 1 #define CLR( a, b ) memset( a, b, sizeof(a) ) #define REP( i, a, b ) for( int i = (a); i < (b); ++i ) #define FOR( i, a, b ) for( int i = (a); i <= (b); ++i ) #define FOD( i, a, b ) for( int i = (a); i >= (b); --i ) #define lson l, m, o << 1 #define rson m + 1, r, o << 1 | 1 #define ls o << 1 #define rs o << 1 | 1 #define root 1, n, 1 #define MAXN 500050 struct SegTree { int l, r; LL sum; LL sub, pre, suf; int subs, sube, pres, pree, sufs, sufe; }tree[ MAXN << 2 ]; void PushUp( int o ) { tree[o].sum = tree[ls].sum + tree[rs].sum; //int l = tree[ls].l, r = tree[rs].r; LL val = tree[ls].pre; int st = tree[ls].pres, ed = tree[ls].pree; if( val < tree[ls].sum + tree[rs].pre ) val = tree[ls].sum + tree[rs].pre, ed = tree[rs].pree; tree[o].pre = val, tree[o].pres = st, tree[o].pree = ed; val = tree[rs].suf; st = tree[rs].sufs, ed = tree[rs].sufe; if( val <= tree[ls].suf + tree[rs].sum ) val = tree[ls].suf + tree[rs].sum, st = tree[ls].sufs; tree[o].suf = val, tree[o].sufs = st, tree[o].sufe = ed; val = tree[ls].sub; st = tree[ls].subs, ed = tree[ls].sube; if( val < tree[ls].suf + tree[rs].pre ) val = tree[ls].suf + tree[rs].pre, st = tree[ls].sufs , ed = tree[rs].pree; if( val < tree[rs].sub ) val = tree[rs].sub, st = tree[rs].subs, ed = tree[rs].sube; tree[o].sub = val, tree[o].subs = st, tree[o].sube = ed; } void Build( int l, int r, int o ) { tree[o]. l = l, tree[o].r = r; if( l == r ) { scanf( "%lld", &tree[o].sum ); tree[o].sub = tree[o].pre = tree[o].suf = tree[o].sum; tree[o].subs = tree[o].sube = tree[o].pres = tree[o].pree = tree[o].sufs = tree[o].sufe = l; return; } int m = MID; Build( lson ); Build( rson ); PushUp( o ); } SegTree Query( int L, int R, int l, int r, int o ) { if( L <= tree[o].l && tree[o].r <= R ) // if( L == tree[o].l && tree[o].r == R ) { return tree[o]; } int m = MID; int ll = 0, rr = 0; SegTree res1, res2, res; if( L <= m ) { res1 = Query( L, R, lson ); ll = 1; } if( R > m ) { res2 = Query( L, R, rson ); rr = 1; } if( ll && !rr ) return res1; if( !ll && rr ) return res2; else { res.pre = res1.pre, res.pres = res1.pres, res.pree = res1.pree; if( res.pre < res1.sum + res2.pre ) res.pre = res1.sum + res2.pre, res.pree = res2.pree; res.suf = res2.suf, res.sufs = res2.sufs, res.sufe = res2.sufe; if( res.suf <= res2.sum + res1.suf ) res.suf = res2.sum + res1.suf, res.sufs = res1.sufs; res.sub = res1.sub, res.subs = res1.subs, res.sube = res1.sube; if( res.sub < res1.suf + res2.pre ) res.sub = res1.suf + res2.pre, res.subs = res1.sufs, res.sube = res2.pree; if( res.sub < res2.sub ) res.sub = res2.sub, res.subs = res2.subs, res.sube = res2.sube; res.sum = res1.sum + res2.sum; return res; } } void Orz() { int m, n, cas = 1; while( ~scanf("%d %d",&n,&m) ) { Build( root ); printf( "Case %d:\n", cas++ ); FOR( i, 1, m ) { int a, b; scanf( "%d %d", &a, &b ); SegTree orz = Query( a, b, root ); printf( "%d %d\n", orz.subs, orz.sube ); } } return; } int main() { Orz(); return 0; }
/* *********************************************** Problem : File Name : Author : Created Time : ************************************************ */ //#define BUG #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <vector> #include <list> #include <queue> #include <ctime> #include <iostream> #include <cmath> #include <set> #include <string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define INF 0x7fffffff #define MAX 0x3f3f3f3f #define CLR( a, b ) memset( a, b, sizeof(a) ) #define REP( i, a, b ) for( int i = (a); i < (b); ++i ) #define FOR( i, a, b ) for( int i = (a); i <=(b); ++i ) #define FOD( i, a, b ) for( int i = (a); i >=(b); --i ) #define MID ( l + r ) >> 1 #define LSON l, m, rt << 1 #define RSON m + 1, r, rt << 1 | 1 #define MAXN 500050 LL Sum[MAXN << 2]; LL Sub[MAXN << 2], sb[MAXN << 2], eb[MAXN << 2]; LL Prefix[MAXN << 2], sp[MAXN << 2], ep[MAXN << 2]; LL Suffix[MAXN << 2], ss[MAXN << 2], es[MAXN << 2]; int m, n, cas = 1; void PushUp(int rt) { Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1]; int l = (rt << 1), r = (rt << 1 | 1); LL Maxval = Prefix[l]; //ŽŠÀíprefixÇé¿ö int st = sp[l], ed = ep[l]; if(Prefix[l] < Sum[l] + Prefix[r]) Maxval = Sum[l] + Prefix[r], st = sp[l], ed = ep[r]; Prefix[rt] = Maxval, sp[rt] = st, ep[rt] = ed; //ŽŠÀísuffixÇé¿ö Maxval = Suffix[r], st = ss[r], ed = es[r]; if(Suffix[r] <= Sum[r] + Suffix[l]) Maxval = Sum[r] + Suffix[l], st = ss[l], ed = es[r]; Suffix[rt] = Maxval, ss[rt] = st, es[rt] = ed; //ŽŠÀíSubÇé¿ö Maxval = Sub[l], st = sb[l], ed = eb[l]; if(Maxval < Suffix[l] + Prefix[r]) Maxval = Suffix[l] + Prefix[r], st = ss[l], ed = ep[r]; if(Maxval < Sub[r]) Maxval = Sub[r], st = sb[r], ed = eb[r]; Sub[rt] = Maxval, sb[rt] = st, eb[rt] = ed; } void Build(int l, int r, int rt) { if(l == r) { scanf("%lld",&Sum[rt]); Sub[rt] = Prefix[rt] = Suffix[rt] = Sum[rt]; sb[rt] = eb[rt] = sp[rt] = ep[rt] = ss[rt] = es[rt] = l; return; } int m = MID; Build(LSON); Build(RSON); PushUp(rt); } struct Orz { LL sum; LL sub,pre,suf; int sb, eb, sp, ep, ss, es; }; Orz Query(int L,int R,int l,int r,int rt) { Orz ret; if(L <= l && r <= R) { Orz tt; tt.pre = Prefix[rt], tt.sub = Sub[rt], tt.suf = Suffix[rt]; tt.sb = sb[rt], tt.eb = eb[rt]; tt.sp = sp[rt], tt.ep = ep[rt]; tt.ss = ss[rt], tt.es = es[rt]; tt.sum = Sum[rt]; return tt; } int m = MID; Orz t1, t2; int ll = 0, rr = 0; if(L <= m) { t1 = Query(L,R,LSON); ll = 1; } if(R > m) { t2 = Query(L,R,RSON); rr = 1; } if(ll && !rr) ret = t1; if(!ll && rr) ret = t2; if(ll && rr) { //ŽŠÀíǰ׺prefix ret.pre = t1.pre, ret.sp = t1.sp, ret.ep = t1.ep; if(ret.pre < t1.sum + t2.pre) ret.pre = t1.sum + t2.pre, ret.ep = t2.ep; //ŽŠÀíºó׺suffix ret.suf = t2.suf, ret.ss= t2.ss, ret.es = t2.es; if(ret.suf <= t2.sum + t1.suf) //ÒòΪÓÐx,yŸ¡Á¿Ð¡ ret.suf = t2.sum + t1.suf, ret.ss = t1.ss; //ŽŠÀí×ÓŽ®Sub ret.sub = t1.sub, ret.sb = t1.sb, ret.eb = t1.eb; if(ret.sub < t1.suf + t2.pre) ret.sub = t1.suf + t2.pre, ret.sb = t1.ss, ret.eb = t2.ep; if(ret.sub < t2.sub) ret.sub = t2.sub, ret.sb = t2.sb, ret.eb = t2.eb; ret.sum = t1.sum + t2.sum; } return ret; } int main() { #ifdef BUG freopen("in.txt","r",stdin); #endif while(~scanf("%d %d",&n,&m)) { //FOR(i,1,n) scanf("%lld",&num[i]); Build(1,n,1); printf("Case %d:\n",cas++); FOR(i,1,m) { int a, b; scanf("%d %d",&a,&b); Orz orz = Query(a,b,1,n,1); printf("%d %d\n",orz.sb,orz.eb); } } return 0; }
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define lc rt<<1 #define rc rt<<1|1 const int maxn = 500000 + 5; typedef long long LL; LL num[maxn], max_prefix[maxn<<2], max_suffix[maxn<<2]; struct node{ int l, r; node(int ll=0, int rr=0):l(ll),r(rr){} } max_sub[maxn<<2]; LL prefix_sum[maxn]; int ql, qr; LL sum(int l, int r){ return prefix_sum[r] - prefix_sum[l-1]; } LL sum(node a){ return sum(a.l, a.r); } node better(node a, node b){ if(sum(a) != sum(b)) return sum(a) > sum(b) ? a:b; return (a.l < b.l||(a.l==b.l&&a.r<b.r))? a : b; } void build(int rt,int l,int r){ if(l == r){ max_prefix[rt] = max_suffix[rt] = l; max_sub[rt] = node(l, l); return ; } int m = (l+r) >> 1; build(lc, l, m); build(rc, m+1, r); LL v1 = sum(l, max_prefix[lc]); LL v2 = sum(l, max_prefix[rc]); if(v1 == v2) max_prefix[rt] = min(max_prefix[lc], max_prefix[rc]); else max_prefix[rt] = v1 > v2 ? max_prefix[lc] : max_prefix[rc]; v1 = sum(max_suffix[lc], r); v2 = sum(max_suffix[rc], r); if(v1 == v2) max_suffix[rt] = min(max_suffix[lc], max_suffix[rc]); else max_suffix[rt] = v1 > v2 ? max_suffix[lc] : max_suffix[rc]; max_sub[rt] = better(max_sub[lc], max_sub[rc]); max_sub[rt] = better(max_sub[rt], node(max_suffix[lc], max_prefix[rc])); } int query_prefix(int rt, int l, int r){ if(qr >= max_prefix[rt]) return max_prefix[rt]; int m = (l+r)>>1; //l<=qr<=m if(qr <= m) return query_prefix(lc, l, m); //m+1<=qr<=r int rr = query_prefix(rc, m+1, r); node ret = better(node(l,rr), node(l, max_prefix[lc])); return ret.r; } int query_suffix(int rt, int l, int r){ if(ql <= max_suffix[rt]) return max_suffix[rt]; int m = (l+r)>>1; //m+1<=ql<=r if(ql > m) return query_suffix(rc, m+1, r); //l<=ql<=m int ll = query_suffix(lc, l, m); node ret = better(node(ll, r), node(max_suffix[rc], r)); return ret.l; } node query(int rt, int l, int r){ if(ql <= l && r <= qr) return max_sub[rt]; int m = (l+r)>>1; if(qr <= m) return query(lc, l, m); if(ql > m) return query(rc, m+1, r); //ql <= m <= qr int ll = query_suffix(lc, l, m); //l_max_suffix int rr = query_prefix(rc, m+1, r); //r_max_prefix node mid = node(ll, rr); node sub = better( query(lc, l, m), query(rc, m+1, r)); return better( mid, sub); } int main() { int n, m, i, cas = 1, l, r; while(~scanf("%d%d", &n, &m)){ printf("Case %d:\n", cas++); prefix_sum[0] = 0; for(i=1; i<=n; ++i) { scanf("%lld", &num[i]); prefix_sum[i] = prefix_sum[i-1] + num[i]; } node v = node(1,3); build(1, 1, n); while(m--){ scanf("%d%d", &l, &r); ql = l; qr = r; node ans = query(1, 1, n); printf("%d %d\n", ans.l, ans.r); } } return 0; }