训练指南上的线段树写法跟平时写的不一样,写得好难受。
<pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define ss(x) scanf("%d",&x)
typedef long long LL;
typedef pair<int,int> Interval;
const int maxn=500000+5;
const int maxnode=1000000+5;
LL pre[maxn];
int n,q;
LL sum(int L,int R) {return pre[R]-pre[L-1];}
LL sum(Interval a) {return sum(a.first,a.second);}
Interval better(Interval a,Interval b){
if(sum(a)!=sum(b)) return sum(a)>sum(b)?a:b;
else return a<b?a:b;
}
int qL,qR;
struct IntervalTree{
int max_pre[maxnode];
int max_suf[maxnode];
Interval max_sub[maxnode];
void BuildTree(int o,int L,int R)
{
if(L==R){
max_pre[o]=max_suf[o]=L;
max_sub[o]=make_pair(L,L);
}
else{
int M=(L+R)/2;
int lc=o*2,rc=o*2+1;
BuildTree(lc,L,M);
BuildTree(rc,M+1,R);
LL v1,v2;
v1=sum(L,max_pre[lc]);
v2=sum(L,max_pre[rc]);
if(v1==v2) max_pre[o]=min(max_pre[lc],max_pre[rc]);
else max_pre[o]=(v1<v2)?max_pre[rc]:max_pre[lc];
v1=sum(max_suf[lc],R);
v2=sum(max_suf[rc],R);
if(v1==v2) max_suf[o]=min(max_suf[lc],max_suf[rc]);
else max_suf[o]=(v1<v2)?max_suf[rc]:max_suf[lc];
max_sub[o]=better(max_sub[lc],max_sub[rc]);
max_sub[o]=better(max_sub[o],make_pair(max_suf[lc],max_pre[rc]));
}
}
Interval query_pre(int o,int L,int R)
{
if(max_pre[o]<=qR) return make_pair(L,max_pre[o]);
int M=(L+R)/2;
int lc=o*2,rc=o*2+1;
if(qR<=M) return query_pre(lc,L,M);
Interval i=query_pre(rc,M+1,R);
i.first=L;
return better(i,make_pair(L,max_pre[lc]));
}
Interval query_suf(int o,int L,int R)
{
if(max_suf[o]>=qL) return make_pair(max_suf[o],R);
int M=(L+R)/2;
int lc=o*2,rc=o*2+1;
if(qL>M) return query_suf(rc,M+1,R);
Interval i=query_suf(lc,L,M);
i.second=R;
return better(i,make_pair(max_suf[rc],R));
}
Interval query(int o,int L,int R)
{
if(qL<=L&&R<=qR) return max_sub[o];
int M=(L+R)/2;
int lc=o*2,rc=o*2+1;
if(qR<=M) return query(lc,L,M);
if(qL>M) return query(rc,M+1,R);
Interval i1=query_pre(rc,M+1,R);
Interval i2=query_suf(lc,L,M);
Interval i3=better(query(lc,L,M),query(rc,M+1,R));
return better(i3,make_pair(i2.first,i1.second));
}
};
IntervalTree tree;
int main()
{
int kase=0;
while(scanf("%d%d",&n,&q)!=EOF)
{
int a;pre[0]=0;
rep(i,0,n) {ss(a);pre[i+1]=pre[i]+a;}
tree.BuildTree(1,1,n);
printf("Case %d:\n",++kase);
while(q--)
{
int a,b;
ss(a);ss(b);
qL=a;qR=b;
Interval ans=tree.query(1,1,n);
printf("%d %d\n",ans.first,ans.second);
}
}
return 0;
}