GSSX -? Can you answer these queries I ~ (continuously updated ...)

GSS - Can you answer these queries I ~ (continuously updated ...)?

\ (\ text {SPOJ} \ ) cancer of the data structure of the series, it is worth doing


GSS I :

A given number of columns \ (A \) , the maximum interval sub-segment support queries and
\ (A [i] \ le 15007, \ N \ le 5e4 \)

Conventional practice segment tree:

//知识点:线段树 
/*
By:Luckyblock
*/
#include <cstdio>
#include <cctype>
#include <algorithm>
#define max std::max
#define ls (now << 1)
#define rs (now << 1 | 1)
const int MARX = 5e4 + 10;
//===========================================================
struct SegmentTree
{
    int L, R;
    int Pre, Suf; //[L,R]的最大 前缀和, 后缀和 
    int Sum, Marx;//[L,R]的和, 最大子段和 
} Tree[MARX << 2];
int N, M, A[MARX];
//===========================================================
inline int read()
{
    int f = 1, w = 0; char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
    return f * w;
}
void Updata(int now) //信息上传 
{
    Tree[now].Sum = Tree[ls].Sum + Tree[rs].Sum; //更新元素和 
    
    Tree[now].Marx = max(Tree[ls].Marx, Tree[rs].Marx); //更新 最大子段和 
    Tree[now].Marx = max(Tree[now].Marx, Tree[ls].Suf + Tree[rs].Pre);
    
    Tree[now].Pre = max(Tree[ls].Pre, Tree[ls].Sum + Tree[rs].Pre); //前缀
    Tree[now].Suf = max(Tree[rs].Suf, Tree[ls].Suf + Tree[rs].Sum); //后缀 
}
void Build(int now, int L, int R) //建树 
{
    Tree[now].L = L, Tree[now].R = R;
    if(L == R) //叶节点 赋初值 
    {
      Tree[now].Pre = Tree[now].Suf = Tree[now].Sum = Tree[now].Marx = A[L];
      return ;
    }
    int mid = (L + R) >> 1;
    Build(ls, L, mid), Build(rs, mid + 1, R);
    Updata(now);
}
SegmentTree Merge(SegmentTree L, SegmentTree R) //将相邻区间L与R的信息进行合并 
{
    SegmentTree ret;
    ret.Sum = L.Sum + R.Sum; //元素和 
    ret.Marx = max(L.Marx, max(R.Marx, L.Suf + R.Pre)); //最大子段和 
    ret.Pre = max(L.Pre, L.Sum + R.Pre); //前缀 
    ret.Suf = max(R.Suf, L.Suf + R.Sum); //后缀 
    return ret;
}
SegmentTree Query(int now, int L, int R) //查询 [L,R]的最大子段和 
{
    if(L <= Tree[now].L && Tree[now].R <= R) return Tree[now]; //被全部包含 
    int mid = (Tree[now].L + Tree[now].R) >> 1;
    if(L > mid) return Query(rs, L, R); //查询区间 只位于右子树 
    if(R <= mid) return Query(ls, L, R);//查询区间 只位于左子树 
    return Merge(Query(ls, L, R), Query(rs, L, R)); //将左右区间合并 
}
//===========================================================
int main()
{
    N = read(); for(int i = 1; i <= N; i ++) A[i] = read();
    Build(1, 1, N);
    M = read();
    for(int i = 1, L, R; i <= M; i ++)
      L = read(), R = read(), 
      printf("%d\n", Query(1, L, R).Marx);
    return 0;
}

GSS2 II:

A given number of columns \ (A \) , the maximum interval support queries and sub-segment, the number of repeating only a contribution
\ (A [i] \ in (- 1e5, 1e5], \ N, Q \ le 5e4 \)


GSS3 III :

A given number of columns \ (A \) , modified single-point support, the largest sub-segment and the query interval
\ (A [i] \ in [- 1e4, 1e4], \ N, Q \ le 5e4 \)

With a modified single-point I, directly on the code:

//知识点:线段树 
/*
By:Luckyblock
*/
#include <cstdio>
#include <cctype>
#include <algorithm>
#define max std::max
#define ls (now << 1)
#define rs (now << 1 | 1)
const int MARX = 5e4 + 10;
//===========================================================
struct SegmentTree
{
    int L, R;
    int Pre, Suf; //[L,R]的最大 前缀和, 后缀和 
    int Sum, Marx;//[L,R]的和, 最大子段和 
} Tree[MARX << 2];
int N, M, A[MARX];
//===========================================================
inline int read()
{
    int f = 1, w = 0; char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
    return f * w;
}
void Updata(int now) //信息上传 
{
    Tree[now].Sum = Tree[ls].Sum + Tree[rs].Sum; //更新元素和 
    
    Tree[now].Marx = max(Tree[ls].Marx, Tree[rs].Marx); //更新 最大子段和 
    Tree[now].Marx = max(Tree[now].Marx, Tree[ls].Suf + Tree[rs].Pre);
    
    Tree[now].Pre = max(Tree[ls].Pre, Tree[ls].Sum + Tree[rs].Pre); //前缀
    Tree[now].Suf = max(Tree[rs].Suf, Tree[ls].Suf + Tree[rs].Sum); //后缀 
}
void Build(int now, int L, int R) //建树 
{
    Tree[now].L = L, Tree[now].R = R;
    if(L == R) //叶节点 赋初值 
    {
      Tree[now].Pre = Tree[now].Suf = Tree[now].Sum = Tree[now].Marx = A[L];
      return ;
    }
    int mid = (L + R) >> 1;
    Build(ls, L, mid), Build(rs, mid + 1, R);
    Updata(now);
}
SegmentTree Merge(SegmentTree L, SegmentTree R) //将相邻区间L与R的信息进行合并 
{
    SegmentTree ret;
    ret.Sum = L.Sum + R.Sum; //元素和 
    ret.Marx = max(L.Marx, max(R.Marx, L.Suf + R.Pre)); //最大子段和 
    ret.Pre = max(L.Pre, L.Sum + R.Pre); //前缀 
    ret.Suf = max(R.Suf, L.Suf + R.Sum); //后缀 
    return ret;
}
SegmentTree Query(int now, int L, int R) //查询 [L,R]的最大子段和 
{
    if(L <= Tree[now].L && Tree[now].R <= R) return Tree[now]; //被全部包含 
    int mid = (Tree[now].L + Tree[now].R) >> 1;
    if(L > mid) return Query(rs, L, R); //查询区间 只位于右子树 
    if(R <= mid) return Query(ls, L, R);//查询区间 只位于左子树 
    return Merge(Query(ls, L, R), Query(rs, L, R)); //将左右区间合并 
}
void Change(int now, int Pos, int Val) //单点修改 
{
    if(Tree[now].L == Tree[now].R && Tree[now].L == Pos) //向下深入至 叶节点 
    {
      Tree[now].Pre = Tree[now].Suf = Tree[now].Sum = Tree[now].Marx = Val;
      return ;
    }
    int mid = (Tree[now].L + Tree[now].R) >> 1;
    if(Pos <= mid) Change(ls, Pos, Val);
    else Change(rs, Pos, Val);
    Updata(now);
}
//===========================================================
int main()
{
    N = read(); for(int i = 1; i <= N; i ++) A[i] = read();
    Build(1, 1, N);
    M = read();
    for(int i = 1; i <= M; i ++)
    {
      int opt = read(), L = read(), R = read();
      if(opt == 0) Change(1, L, R);
      else printf("%d\n", Query(1, L, R).Marx); 
    } 
    return 0;
}

This thing seems to be a dynamic \ (DP \? \) And even more after learned.


GSS IV :

Given a number of columns \ (A \) , support section square root operation, the query section, and
\ (\ sum \ limits_ {i = 1} ^ {N} A [i] \ le 10 ^ {18}, \ N, M \ le 1e5 \)

Block classic operation, but this question card out of the block,
the block thinking applied to the tree line.

Since the root operation does not meet a series of operational law, you can not use the notation.

How do? Consider direct violence.
As we all know, \ (\ Bigg \ lfloor \ sqrt {\ sqrt {\ sqrt {\ sqrt {\ sqrt {\ sqrt {10 ^ {18}}}}}}} \ Bigg \ rfloor = 1 \) .
for a number, after up to 6 times must be equal to 1. Review
and \ (\ = sqrt {}. 1. 1 \) , to modify its operation will not be affected.

It can record the number of times the square root of each of a range.
If the number of prescribing \ (> 5 \) , regardless of the number of its modifications, elements, and will not change, no modification operations.
Otherwise depth directly to modify the leaf node violence, and complete update on the number of times when modifying violence.

//知识点:线段树 
/*
By:Luckyblock
*/
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ls (now << 1)
#define rs (now << 1 | 1)
#define ll long long
const int MARX = 1e5 + 10;
//===========================================================
struct SegmentTree
{
    int L, R, Num;
    ll Sum;
} Tree[MARX << 2];
int N, M, T;
ll Original[MARX];
//===========================================================
inline ll read()
{
    ll f = 1, w = 0; char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
    return f * w;
}
void PushUp(int now) {Tree[now].Sum = Tree[ls].Sum + Tree[rs].Sum;} //更新区间和 
void Build(int now, int L, int R) //建树 
{
    Tree[now].L = L, Tree[now].R = R;
    if(L == R) {Tree[now].Sum = (ll) Original[L]; return ;}
    int mid = (L + R) >> 1;
    Build(ls, L, mid), Build(rs, mid + 1, R);
    PushUp(now);
}
void Change(int now, int L, int R) //区间修改 
{
    if(Tree[now].Num > 5) return ; //已全为1, 不需修改 
    if(L <= Tree[now].L && Tree[now].R <= R)
    {
      Tree[now].Num ++; //更新开方次数 
      if(Tree[now].L == Tree[now].R) //若为叶节点. 暴力修改 
      {
        Tree[now].Sum = sqrt(Tree[now].Sum);
        return ;
      }
    }
    int mid = (Tree[now].L + Tree[now].R) >> 1;
    if(L <= mid) Change(ls, L, R);
    if(R > mid) Change(rs, L, R);
    PushUp(now);
}
ll Query(int now, int L, int R) //查询区间和 
{
    if(L <= Tree[now].L && Tree[now].R <= R) return Tree[now].Sum;
    int mid = (Tree[now].L + Tree[now].R) >> 1;
    ll ret = 0;
    if(L <= mid) ret += Query(ls, L, R);
    if(R > mid) ret += Query(rs, L, R);
    return ret;
}
//===========================================================
int main()
{
    while(scanf("%d", &N) != EOF)
    {
      memset(Tree, 0, sizeof(Tree)); printf("Case #%d:\n", ++ T);
      for(int i = 1; i <= N; i ++) Original[i] = read();
      Build(1, 1, N);
      M = read();
      while(M --)
      {
        int opt = (int) read(), x = (int) read(), y = (int) read();
        if(x > y) std :: swap(x, y);
        if(! opt) Change(1, x, y);
        else printf("%lld\n", Query(1, x, y));
      }
      printf("\n");
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/luckyblock/p/12150531.html