嘘~ 正在从服务器偷取页面 . . .

SP2916 GSS5 - Can you answer these queries V 题解


SP2916 GSS5 - Can you answer these queries V 题解

题目链接:SP2916 GSS5 - Can you answer these queries V

题意

多组数据。每组数据给定一个长度为 \(n\) 的序列 \(a_i\)

\(q\) 次询问,查询左端点在 \([x_1, y_1]\) 之间,且右端点在 \([x_2, y_2]\) 之间的最大子段和

数据保证 \(x_1\leq x_2,y_1\leq y_2\) ,但是不保证端点所在的区间不重合。

数据范围

\(1 \le T\le 5, ~1\le n \le 10^4,~ |a_i| \le 10^4,~1\le q \le 10^4\)

首先要先做下 GSS1 或 GSS3 ,知道怎么用线段树维护区间最大子段和。

然后这道题其实只是在询问上做了一些修改。

对于 \(r_1 < l_2\) 的情况,很简单,就是 \([l_1,r_1]\)\(\mathtt{pre}\)\([l_2,r_2]\)\(\mathtt{suf}\)\([r_1 + 1, l_2-1]\)\(\mathtt{sum}\)

对于有交集的情况就比较麻烦了。不失一般性,考虑 \(l_1 < l_2 < r_1 < r_2\) 的情况。

则有以下三种情况:

tmp = query(l2,r1).res;
if(l1 < l2) up(tmp, query(l1,l2).suf + query(l2,r2).pre - a[l2]);
if(r2 > r1) up(tmp, query(l1,r1).suf + query(r1,r2).pre - a[r1]);
cout << tmp << '\n';

好像没啥好说的了,怪不得 GSS 系列要集体掉色。

时间复杂度 \(\mathcal{O}(n \log n)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define DD(x) cout << #x << '=' << x << '\n';
#define DDD cout << "Line here is " << __LINE__ << '\n';
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
namespace FastIO
{
    #define gc() readchar()
    #define pc(a) putchar(a)
    #define SIZ (int)(1e6+15)
    char buf1[SIZ],*p1,*p2;
    char readchar()
    {
        if(p1==p2)p1=buf1,p2=buf1+fread(buf1,1,SIZ,stdin);
        return p1==p2?EOF:*p1++;
    }
    template<typename T>void read(T &k)
    {
        char ch=gc();T x=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
        k=x*f;
    }
    template<typename A, typename ...B>
        void read(A &x, B &...y) { return read(x), read(y...); }
    template<typename T>void write(T k)
    {
        if(k<0){k=-k;pc('-');}
        static T stk[66];T top=0;
        do{stk[top++]=k%10,k/=10;}while(k);
        while(top){pc(stk[--top]+'0');}
    }
}using namespace FastIO;
#define N ((int)(1e5+15))
#define N4 (N * 4)

int n,a[N],sum[N4],res[N4],pre[N4],suf[N4];
struct qry { int sum,pre,suf,res; }tmp;
#define ls(at) ((at) << 1)
#define rs(at) ((at) << 1 | 1)
void push_up(int at)
{
    int l = ls(at), r = rs(at);
    sum[at] = sum[l] + sum[r];
    up(pre[at] = pre[l], sum[l] + pre[r]);
    up(suf[at] = suf[r], sum[r] + suf[l]);
    res[at] = max({res[l], res[r], suf[l] + pre[r]});
}
void build(int l,int r,int at)
{
    if(l == r)
    {
        sum[at] = res[at] = pre[at] = suf[at] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(l,mid,ls(at)); build(mid+1,r,rs(at));
    push_up(at);
}
void modify(int x,int y,int l,int r,int at)
{
    if(l==r)
    {
        sum[at]=res[at]=pre[at]=suf[at]=a[l]=y;
        return;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) modify(x,y,l,mid,ls(at));
    else modify(x,y,mid+1,r,rs(at));
    push_up(at);
}
qry query(int nl,int nr,int l = 1,int r = n,int at = 1)
{
    if(nl > nr) return {0,0,0,0};
    if(nl <= l && r <= nr)
        return {sum[at], pre[at], suf[at], res[at]};
    int mid = (l + r) >> 1;
    if(nr <= mid) return query(nl,nr,l,mid,ls(at));
    if(nl > mid) return query(nl,nr,mid+1,r,rs(at));
    qry L = query(nl,nr,l,mid,ls(at));
    qry R = query(nl,nr,mid+1,r,rs(at));
    tmp.sum = L.sum+R.sum;
    up(tmp.pre = L.pre, L.sum + R.pre);
    up(tmp.suf = R.suf, R.sum + L.suf);
    tmp.res = max({ L.res, R.res, L.suf + R.pre });
    return tmp;
}
void solve()
{
    cin >> n; for(int i=1; i<=n; i++) cin >> a[i]; build(1,n,1);
    int Q; cin >> Q; for(int l1,r1,l2,r2,tmp; Q--; )
    {
        cin >> l1 >> r1 >> l2 >> r2;
        if(r1 < l2)
        {
            tmp = query(l1, r1).suf;
            tmp += query(r1+1, l2-1).sum;
            tmp += query(l2, r2).pre;
            cout << tmp << '\n';
        }else
        {
            tmp = query(l2,r1).res;
            if(l1 < l2) up(tmp, query(l1,l2).suf + query(l2,r2).pre - a[l2]);
            if(r2 > r1) up(tmp, query(l1,r1).suf + query(r1,r2).pre - a[r1]);
            cout << tmp << '\n';
        }
    }
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int _Q; cin >> _Q; while(_Q--) solve();
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录