训练指南上的例题。
可以使用Splay解决,维护区间最大连续值即可,在维护输出要求这里比较复杂,需要考虑清楚,L最小和R最小。
注意要用longlong。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#define Value ch[ch[root][1]][0]
using namespace std;
typedef long long LL;
const int maxn=500005;
int n;
int a[maxn];
struct Splay
{
int tot,root,cnt;
int ch[maxn][2],pre[maxn],size[maxn],val[maxn],num[maxn];
LL lx[maxn],rx[maxn],mx[maxn],sum[maxn];
int l_r[maxn],r_l[maxn],m_l[maxn],m_r[maxn];
void newNode(int &x,int f,int v)
{
x=++tot;
ch[x][0]=ch[x][1]=0;
pre[x]=f;
sum[x]=val[x]=v;
lx[x]=rx[x]=mx[x]=v;
size[x]=1;
l_r[x]=r_l[x]=m_l[x]=m_r[x]=n+1;
}
void push_up(int x)
{
int ls=ch[x][0],rs=ch[x][1];
size[x]=size[ls]+size[rs]+1;
sum[x]=sum[ls]+sum[rs]+val[x];
if(ls==0)
{
lx[x]=val[x];
l_r[x]=num[x];
if(rs!=0&&lx[x]<val[x]+lx[rs])
{
lx[x]=val[x]+lx[rs];
l_r[x]=l_r[rs];
}
}
else
{
lx[x]=lx[ls];
l_r[x]=l_r[ls];
if(lx[x]<sum[ls]+val[x])
{
lx[x]=sum[ls]+val[x];
l_r[x]=num[x];
}
if(rs!=0&&lx[x]<sum[ls]+val[x]+lx[rs])
{
lx[x]=sum[ls]+val[x]+lx[rs];
l_r[x]=l_r[rs];
}
}
if(rs==0)
{
rx[x]=val[x];
r_l[x]=num[x];
if(ls!=0&&rx[x]<=val[x]+rx[ls])
{
rx[x]=val[x]+rx[ls];
r_l[x]=r_l[ls];
}
}
else
{
rx[x]=rx[rs];
r_l[x]=r_l[rs];
if(rx[x]<=sum[rs]+val[x])
{
rx[x]=sum[rs]+val[x];
r_l[x]=num[x];
}
if(ls!=0&&rx[x]<=sum[rs]+val[x]+rx[ls])
{
rx[x]=sum[rs]+val[x]+rx[ls];
r_l[x]=r_l[ls];
}
}
mx[x]=val[x];
m_l[x]=num[x];
m_r[x]=num[x];
if(ls!=0&&rx[ls]>=0)
{
mx[x]+=rx[ls];
m_l[x]=r_l[ls];
}
if(rs!=0&&lx[rs]>0)
{
mx[x]+=lx[rs];
m_r[x]=l_r[rs];
}
if(ls!=0)
{
if(mx[ls]>mx[x])
{
mx[x]=mx[ls];
m_l[x]=m_l[ls];
m_r[x]=m_r[ls];
}
else if(mx[ls]==mx[x])
{
if(m_l[ls]<m_l[x])
{
m_l[x]=m_l[ls];
m_r[x]=m_r[ls];
}
else if(m_l[ls]==m_l[x]&&m_r[ls]<m_r[x])
{
m_r[x]=m_r[ls];
}
}
}
if(rs!=0)
{
if(mx[rs]>mx[x])
{
mx[x]=mx[rs];
m_l[x]=m_l[rs];
m_r[x]=m_r[rs];
}
else if(mx[rs]==mx[x])
{
if(m_l[rs]<m_l[x])
{
m_l[x]=m_l[rs];
m_r[x]=m_r[rs];
}
else if(m_l[rs]==m_l[x]&&m_r[rs]<m_r[x])
{
m_r[x]=m_r[rs];
}
}
}
}
void build(int &x,int f,int l,int r)
{
if(l>r) return ;
int m=l+(r-l)/2;
newNode(x,f,a[m]);
build(ch[x][0],x,l,m-1);
num[x]=++cnt;
build(ch[x][1],x,m+1,r);
push_up(x);
}
void init()
{
tot=cnt=root=0;
newNode(root,0,-1);
newNode(ch[root][1],root,-1);
for(int i=0; i<n; ++i)
scanf("%d",&a[i]);
build(Value,ch[root][1],0,n-1);
//num[ch[root][1]]=++cnt;
//num[root]=++cnt;
push_up(ch[root][1]);
push_up(root);
}
int getKth(int x,int k)
{
int t=size[ch[x][0]]+1;
if(t==k)
return x;
else if(k<t)
return getKth(ch[x][0],k);
else
return getKth(ch[x][1],k-t);
}
void rotate(int x,int kind)
{
int y=pre[x];
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
push_up(y);
}
void adjust(int x,int g)
{
while(pre[x]!=g)
{
if(pre[pre[x]]==g)
{
rotate(x,ch[pre[x]][0]==x);
}
else
{
int y=pre[x];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x)
{
rotate(x,!kind);
rotate(x,kind);
}
else
{
rotate(y,kind);
rotate(x,kind);
}
}
}
push_up(x);
if(g==0)
root=x;
}
void getAnswer(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,r+2),root);
printf("%d %d\n",m_l[Value],m_r[Value]);
}
};
Splay tree;
int main()
{
int m,kase=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
tree.init();
printf("Case %d:\n",++kase);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
tree.getAnswer(x,y);
}
}
return 0;
}