社区讨论

线段树做法求助

P1440求m区间内的最小值参与者 8已保存回复 10

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
10 条
当前快照
1 份
快照标识符
@mi6mjvmc
此快照首次捕获于
2025/11/20 07:19
4 个月前
此快照最后确认于
2025/11/20 07:19
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
#define ll int
using namespace std;
ll n, m;
ll L = 1, a[500100];
struct st
{
    ll left, right;
    ll lazy, s;
}t[500005];

inline int read() 
{
    int x=0, f = 1; 
    char ch=getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x *= 10; 
        x += (ch-'0');
        ch = getchar();
    }
    return x * f;
}

inline void write(int x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
void build_tree()
{
    while(L < n) L *= 2;
    for(ll i = 1; i <= n; i++) 
        t[i + L - 1].left = t[i + L - 1].right = i, 
        t[i + L - 1].s = a[i];
    for(ll i = L + n;i < 2 * L;i++)
        t[i].left = t[i].right = i - L + 1;
    for(ll i = L - 1; i >= 1; i--)
        t[i].left = t[2 * i].left,
        t[i].right = t[2 * i + 1].right,
        t[i].s = min(t[2 * i + 1].s, t[2 * i].s);
}
ll query(ll id, ll left, ll right)
{
    if(t[id].left == left && t[id].right == right)
        return t[id].s;
    if(t[2 * id].right >= right) return query(2 * id, left, right);
    else if(t[2 * id + 1].left <= left) return query(2 * id + 1, left, right);
    else return min(query(2 * id, left, t[2 * id].right), query(2 * id + 1, t[2 * id + 1].left, right));
}
int main(int argc, char *argv[])
{
    n = read();
    m = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    build_tree();
    for(int i = 1; i <= n; i++)
    {
        if(i == 1) write(0);
        else if(i <= m) write(query(1, 1, i - 1));
        else if(i > m) write(query(1, i - m, i - 1));
        printf("\n");
    }
    return 0;
}
CPP
#2加了输入输出后卡过(900ms+),#10永远的TLE求大佬优化。

回复

10 条回复,欢迎继续交流。

正在加载回复...