NC11166 J.Journey among Railway Stations(线段树+两点)

目录

Description

\(n\) 个站台,每个站台都有一个可以通过的时间 \([u_i,v_i]\) ,每两个站台之间有一条路径,共 \(n-1\) 条,\(Q\) 次询问区间 \([l,r]\),从 \(u_l\) 时间出发能否通过 \(r\) 站台

State

\(1<=T<=10^4\)

\(2<=n<=10^6\)

\(1<=u<=v<=10^9\)

\(1<=cost<=10^9\)

\(1<=Q<=10^6\)

Input

1
5
1 2 3 4 5
3 4 5 6 7
1 1 1 1
5
0 1 5
1 1 3
0 1 5
2 2 2 3
0 1 5

Output

Yes
Yes
No

Solution

假设有三个站台 \([u_1,v_1],[u_2,v_2],[u_3,v_3]\)

他们分别满足的条件为

\[u_1<=v_1 \\ max(u_1+d_1,u_2)<=v_2 \\ max(u_1+d_1+d_2,u_2+d_2,u_3)<=v_3 \\ \]

根据这些条件,可以在 \(O(n)\) 内查询出是否可以通过,但这还远远不够;

但目前为止,并没有很好的解决办法,但是如果变成以下的式子

\[u_1+d_1+d_2<=v_1+d_1+d_2 \\ max(u_1+d_1+d_2,u_2+d_2)<=v_2+d_2 \\ max(u_1+d_1+d_2,u_2+d_2,u_3)<=v_3 \\ \]

题目就有迹可循了,如果相邻的两个节点 \(i,j\) 可以通过,那么一定有 \(u_i<=v_j\)


Code

const int N = 1e6 + 5;
 
    int n, m, k, _;
    int a[N];
    int b[N];
    struct Node
    {
        ll minn, maxx;
        ll lazy;
        bool ok;
        // Node(ll minn = 0, ll maxx = 0, ll lazy = 0, bool ok = 0) : minn(minn), maxx(maxx), lazy(lazy), ok(ok){}
        #define lson id << 1
        #define rson id << 1 | 1
        void update(ll x)
        {
            maxx += x;
            minn += x;
            lazy += x;
        }
    }t[N << 2];
    int c[N];
    ll sum[N];

Node merge(Node a, Node b)
{
    Node ans;
    ans.maxx = max(a.maxx, b.maxx);
    ans.minn = min(a.minn, b.minn);
    ans.ok = a.ok && b.ok;
    if(a.maxx > b.minn) ans.ok = 0;
    return ans;
}

void push_up(int id)
{
    ll x = t[id].lazy;
    t[id] = merge(t[lson], t[rson]);
    t[id].lazy = x;
}

void push_down(int id)
{
    ll x = t[id].lazy;
    if(x){
        t[lson].update(x);
        t[rson].update(x);
        t[id].lazy = 0;
    }
}

void build(int l, int r, int id)
{
    t[id].ok = t[id].lazy = 0;
    if(l == r){
        t[id].maxx = sum[l] + a[l];
        t[id].minn = sum[l] + b[l];
        t[id].ok = 1;
    }
    else{
        int mid = l + r >> 1;
        build(l, mid, lson);
        build(mid + 1, r, rson);
        push_up(id);
    }
}

void update(int l, int r, ll ca, ll cb, int id, int opt, int L = 1, int R = n)
{
    if(L >= l && r >= R){
        if(opt){
            t[id].maxx += ca;
            t[id].minn += cb;
        }
        else t[id].update(ca);
    }
    else{
        int mid = L + R >> 1;
        push_down(id);
        if(mid >= l) update(l, r, ca, cb, lson, opt, L, mid);
        if(r >= mid + 1) update(l, r, ca, cb, rson, opt, mid + 1, R);
        push_up(id);
    }
}

Node query(int l, int r, int id, int L = 1, int R = n)
{
    if(L == l && R == r){
        return t[id];
    }
    else{
        int mid = L + R >> 1;
        push_down(id);
        if(mid >= r) return query(l, r, lson, L, mid);
        else if(l >= mid + 1) return query(l, r, rson, mid + 1, R);
        else return merge(query(l, mid, lson, L, mid), query(mid + 1, r, rson, mid + 1, R));
    }
}

signed main()
{
    //IOS;
    rush(){
        sd(n);
        rep(i, 1, n) sd(a[i]);
        rep(i, 1, n) sd(b[i]);
        rep(i, 1, n - 1) sd(c[i]);
        sum[n] = 0;
        for(int i = n - 1; i; i --) sum[i] = sum[i + 1] + c[i];
        build(1, n, 1);
        sd(m);
        int x, y, pos, w, opt;
        while(m --> 0){
            sd(opt);
            if(opt == 0){
                sdd(x, y);
                bool ok = query(x, y, 1).ok;
                // dbg(query(x, y, 1).maxx);
                // dbg(query(x, y, 1).minn);
                if(ok) puts("Yes");
                else puts("No");
            }
            else if(opt == 1){
                sdd(pos, w);
                //for(int i = 1; i <= pos; i ++) update(i, i, w - c[pos], w - c[pos], 1, 1);
                update(1, pos, w - c[pos], w - c[pos], 1, 0);
                c[pos] = w;
            }
            else{
                sddd(pos, x, y);
                update(pos, pos, x - a[pos], y - b[pos], 1, 1);
                a[pos] = x;
                b[pos] = y;
            }
        }
    }
    //PAUSE;
    return 0;
}
posted @ 2021-10-05 09:00  Bcoi  阅读(86)  评论(0)    收藏  举报