SOS!求助:线段树70分,剩下30TLE。

P1253 扶苏的问题

Swiftie_wyc22 @ 2022-02-14 08:50:40

怎么优化才能AC

#include <bits/stdc++.h>
#define int long long 
using namespace std;
int n, q;
struct Tree
{
    int left, right;
    int max;
    int delta;
};
Tree tree[4 * 5000000 + 10];
int a[500010];
int queryAns = 0; 
void build (int id, int l, int r)
{
    tree[id].left = l;
    tree[id].right = r;

    if (l == r)
    {
        tree[id].max = a[l];
    }
    else
    {
        int mid = (l + r) / 2;
        build(id * 2, l, mid);
        build(id * 2 + 1, mid + 1, r);

        tree[id].max = max(tree[id * 2].max, tree[id * 2 + 1].max);
    }
}

void change(int id, int l, int r, int val)
{
    if (tree[id].left > r || tree[id].right < l)
        return ;
    if (tree[id].left >= l && tree[id].right <= r)
    {
//      cout << "DEBUG" << endl;
        tree[id].max = val;
        tree[id].delta = val;
    }
    if (tree[id].delta)
    {
        tree[id * 2].max = val;
        tree[id * 2 + 1].max = val;
        tree[id * 2].delta = tree[id].delta;
        tree[id * 2 + 1].delta = tree[id].delta;
        tree[id].delta = 0;
    }
    change(2 * id, l, r, val);
    change(2 * id + 1, l, r,val);
    tree[id].max = max(tree[id * 2].max, tree[id * 2 + 1].max);
}

void update(int id, int l, int r, int delta)
{
    if (tree[id].left > r || tree[id].right < l)
        return;
//  if (tree[id].left == tree[id].right)
//      tree[id].max += delta;

    if (tree[id].left >= l && tree[id].right <= r)
    {
        tree[id].max += delta;
        tree[id].delta += delta;
        return;
    }
    if (tree[id].delta)
    {
        tree[id * 2].max += tree[id].delta; // pushdown
        tree[id * 2 + 1].max += tree[id].delta; // pushdown
        tree[id * 2].delta += tree[id].delta;
        tree[id * 2 + 1].delta += tree[id].delta;
        tree[id].delta = 0;
    }

    update(2 * id, l, r, delta);
    update(2 * id + 1, l, r, delta);
    tree[id].max = max(tree[id * 2].max, tree[id * 2 + 1].max);
}

void query(int id, int l, int r)
{
    if (tree[id].left > r || tree[id].right < l)
        return;
    if (tree[id].left >= l && tree[id].right <= r)
    {
        queryAns = max(queryAns, tree[id].max);
        return;
    }
    if (tree[id].delta)
    {
        tree[id * 2].max += tree[id].delta;
        tree[id * 2].delta += tree[id].delta;
        tree[id * 2 + 1].max += tree[id].delta;
        tree[id * 2 + 1].delta += tree[id].delta;
        tree[id].delta = 0;
    }
    query(2 * id, l, r);
    query(2 * id + 1, l, r);
    tree[id].max = max(tree[id * 2].max , tree[id * 2 + 1].max);
} 

void print_tree(int id)
{
    if (tree[id].left == tree[id].right)
    {
        printf("id = %lld, max = %lld, tree[id].left = %lld, tree[id].right = %lld \n", id, tree[id].max, tree[id].left, tree[id].right);
//      cout << tree[id].max << " ";
        return;
    }
    printf("id = %lld, max = %lld, tree[id].left = %lld, tree[id].right = %lld \n", id, tree[id].max, tree[id].left, tree[id].right);
    print_tree(id * 2);
    print_tree(id * 2 + 1);
}

signed main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);

    build(1, 1, n);
//  print_tree(1);

    int op, x, l, r;
    while (q--)
    {
        cin >> op;
        if (op == 1)
        {
            scanf("%lld %lld %lld", &l, &r, &x);
            change(1, l, r, x);
//          print_tree(1);cout << endl;
        }
        else if (op == 2)
        {
            scanf("%lld %lld %lld", &l, &r, &x);
            update(1, l, r, x);
//          print_tree(1);cout << endl;
        }
        else
        {
            scanf("%lld %lld", &l, &r);
            queryAns = LLONG_MIN; query(1, l, r);
            printf("%lld\n", queryAns);
        }
    }
    return 0;
}

by BootsH @ 2022-02-14 08:53:29

把不需要 long long 的数改成 int


by Swiftie_wyc22 @ 2022-02-15 12:08:53

@developer6hyx 不行呀


by Swiftie_wyc22 @ 2022-02-15 12:10:59

@liweiang09

上次我的线段树问题您帮我解决了,您还能看看这个嘛?


by Liweiang @ 2022-02-15 14:55:03

@Aeterna 把区间覆盖和区间加的标记分开搞,每次下传的时候先下传覆盖标记,如果有覆盖标记就把加法标记清零。代码你调不出来了再问


|