您的位置:首页 > 其它

Uva 1400 "Ray, Pass me the dishes!" (线段树 区间合并)

2014-08-13 20:50 465 查看
这道题是训练指南上的一道例题,今天照着书上的标程敲了一遍,学了一下他的线段树写法。由于求的是一个区间,所以用pair来做结点,非常方便。在求区间和的时候先预处理一个前缀和,这样就可以用O(1)的复杂度求任意区间的和。这道题的难点在于区间合并。

一个区间上和最大的子区间等于这个区间的两个子区间的最大子区间的最大值和 左区间的最大后缀加上右区间的最大前缀三者中最大的和。也就是以下式子:

PII i1 = query_rmax(lson);
PII i2 = query_lmax(rson);
PII i3 = better(query(lson),query(rson));
return better(make_pair(i1.first,i2.second),i3);


而最大后缀和最大前缀都是可以递归处理出来的(虽然比较繁琐。。。基本照搬书上代码)

把AC代码粘出来(实在太弱了我。。)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
using namespace std;
const int maxn = 500005;
typedef pair<int ,int> PII;
int qL,qR;
LL sum[maxn];
LL getsum(int L,int R){
return sum[R]-sum[L-1];
}

LL getsum(PII p){
return getsum(p.first,p.second);
}
PII better(PII a,PII b){
if(getsum(a)!=getsum(b))return getsum(a)>getsum(b)?a:b;
return a<b?a:b;
}

struct xdTree{
int lmax[maxn<<2];
int rmax[maxn<<2];
PII mmax[maxn<<2];

void build(int l,int r,int rt){
if(l == r){
lmax[rt] = rmax[rt] = l;
mmax[rt] = make_pair(l,l);
}else{
int m = (l+r)>>1;
build(lson);
build(rson);

LL v1 = getsum(l,lmax[rt<<1]);
LL v2 = getsum(l,lmax[rt<<1|1]);
if(v1==v2)lmax[rt] = min(lmax[rt<<1],lmax[rt<<1|1]);
else lmax[rt] = v1>v2?lmax[rt<<1]:lmax[rt<<1|1];

v1 = getsum(rmax[rt<<1],r);
v2 = getsum(rmax[rt<<1|1],r);
if(v1 == v2)rmax[rt] = min(rmax[rt<<1],rmax[rt<<1|1]);
else rmax[rt] = v1>v2?rmax[rt<<1]:rmax[rt<<1|1];

mmax[rt] = better(mmax[rt<<1],mmax[rt<<1|1]);
mmax[rt] = better(mmax[rt],make_pair(rmax[rt<<1],lmax[rt<<1|1]));
}
}

PII query_lmax(int l,int r,int rt){
if(lmax[rt]<=qR) return make_pair(l,lmax[rt]);
int m = (l+r)>>1;
if(qR<=m)return query_lmax(lson);
PII i = query_lmax(rson);
i.first = l;
return better(i,make_pair(l,lmax[rt<<1]));
}
PII query_rmax(int l,int r,int rt){
if(rmax[rt]>=qL) return make_pair(rmax[rt],r);
int m = (l+r)>>1;
if(qL>m)return query_rmax(rson);
PII i = query_rmax(lson);
i.second = r;
return better(i,make_pair(rmax[rt<<1|1],r));
}
PII query(int l,int r,int rt){
if(qL<=l&&r<=qR)return mmax[rt];
int m = (l+r)>>1;
if(qR<=m)return query(lson);
if(qL>m)return query(rson);
PII i1 = query_rmax(lson); PII i2 = query_lmax(rson); PII i3 = better(query(lson),query(rson)); return better(make_pair(i1.first,i2.second),i3);
}
}tree;

int main(){
int cas = 1,n,q,temp;
while(scanf("%d%d",&n,&q)==2){
sum[0] = 0;
for(int i=1;i<=n;i++){
scanf("%d",&temp);
sum[i] = sum[i-1]+temp;
}
tree.build(1,n,1);
printf("Case %d:\n",cas++);
while(q--){
scanf("%d%d",&qL,&qR);
PII ans = tree.query(1,n,1);
printf("%d %d\n",ans.first,ans.second);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: