【Shadow 1】第三题
“南山经之首曰鹊山。其首曰招摇之山,临于西海之上。多桂多金玉。有草焉,其状如韭而青华,其名曰祝馀,食之不饥……
又东三百里曰堂庭之山。金棪木,多白猿,多水玉,多黄金。
又东三百八十里曰猨翼之山。其中多怪兽,水多怪鱼。多白玉,多蝮虫,多怪蛇,多怪木,不可以上……”
《山海经》是以山为纲,以海为线记载古代的河流、植物、动物以及矿产等情况,而且每一条记录路线都不会有重复的山出现。某天,wyl8899想游览《山海经》中的路线,为了简化问题,wyl8899已经把每座山用一个整数表示他对该山的喜恶程度。wyl8899想知道第a座山到第b座山的中间某短路[i,j]能使他感到最满意,即[i,j]这条路上所有山的喜恶程度之和是所有c,d最大。由于wyl8899还要去WJMZBMR家里【哗……】,所以他把这个问题扔给了Shadow:“你做不出来就……”
第1行,2个整数N,M,N表示一共有N座山,M表示wyl8899想问的次数(Shadow:问那么多干嘛……);
第2行,N个整数,代表N座山的喜恶程度,绝对值均小于10000;
第3-(M+2)行,每行有2个数a,b,表示询问从第a座山到第b座山的最大值。
输出描述 Output Description
一共有M行,每行有3个数i,j,s,表示从第i座山到第j座山总的喜恶程度为s。显然,对于每个询问,有a≤i≤j≤b,如果有多组解,则输出i最少的,如果i也相等,则输出j最少的解。
5 3
5 -6 3 -1 4
1 3
1 5
5 5
1 1 5
3 5 6
5 5 4
对于100%的数据,2≤N≤200000,1≤M≤100000,1≤a≤b≤N。
填了个史前巨坑
维护个区间最大子段和,要维护左右端点…好吧左右端点好恶心
然后机智的我重载加号和小于号…然后交上去还是WA…我以为我不知道哪写错了…然后开始各种改,借鉴抄黄学长博客什么的…
调了一个小时发现值没求错!端点不是最优!!然后开始输出重载加号!后来发现加号没错然后去看小于号,之后才发现是重载小于号出毛病了…改了个大于号小于号成功AC…我这智商也是没谁了…
好像我没写过线段树维护区间最大子段和…我写的是splay…
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int SZ = 1000010;
const int INF = 1000000010;
struct haha{
int l,r,x;
void print()
{
printf("%d %d %d\n",l,r,x);
}
};
bool operator <(const haha &a,const haha &b)
{
return a.x < b.x || (a.x == b.x && a.l > b.l) || (a.x == b.x && a.l == b.l && a.r > b.r);
}
haha operator +(haha a,haha b)
{
haha c;
c.l = min(a.l,b.l); c.r = max(a.r,b.r); c.x = a.x + b.x;
return c;
}
struct segment{
int l,r;
haha sum,lx,rx,mx;
}tree[SZ << 2];
void update(int p)
{
int lch = p << 1,rch = p << 1 | 1;
tree[p].sum = tree[lch].sum + tree[rch].sum;
tree[p].lx = max(tree[lch].lx,tree[lch].sum + tree[rch].lx);
tree[p].rx = max(tree[rch].rx,tree[lch].rx + tree[rch].sum);
tree[p].mx = max(max(tree[lch].mx,tree[rch].mx),tree[lch].rx + tree[rch].lx);
}
int num[SZ];
void build(int p,int l,int r)
{
tree[p].l = l;
tree[p].r = r;
if(l == r)
{
tree[p].sum = tree[p].mx = tree[p].lx = tree[p].rx = (haha){l,r,num[l]};
return ;
}
int mid = l + r >> 1;
build(p << 1,l,mid);
build(p << 1 | 1,mid + 1,r);
update(p);
}
segment ask(int p,int l,int r)
{
if(l == tree[p].l && tree[p].r == r)
return tree[p];
int mid = tree[p].l + tree[p].r >> 1;
if(r <= mid) return ask(p << 1,l,r);
else if(l > mid) return ask(p << 1 | 1,l,r);
else
{
segment a,b,c;
a = ask(p << 1,l,mid); b = ask(p << 1 | 1,mid + 1,r);
c.mx = max(max(a.mx,b.mx),a.rx + b.lx);
c.lx = max(a.lx,a.sum + b.lx);
c.rx = max(b.rx,a.rx + b.sum);
c.sum = a.sum + b.sum;
c.l = l; c.r = r;
return c;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i ++)
scanf("%d",&num[i]);
build(1,1,n);
for(int i = 1;i <= m;i ++)
{
int l,r;
scanf("%d%d",&l,&r);
segment f = ask(1,l,r);
printf("%d %d %d\n",f.mx.l,f.mx.r,f.mx.x);
}
return 0;
}