Live2D

Solution -「JOISC 2021」「LOJ #3489」饮食区

\(\mathcal{Description}\)

  Link.

  呐……不想概括题意,自己去读叭~

\(\mathcal{Solution}\)

  如果仅有 1. 3. 操作,能不能做?

  ——简单整体二分。

  如果仅有 1. 2. 操作,能不能实时维护每个位置还剩下多少人?累计走了多少人?

  ——吉司机线段树。

  所以,离线下来,把上两个重工业揉在一起就能粗暴地过掉这道题√ 复杂度 \(\mathcal O(n\log^2n)\)\(n,m,q\) 同阶)。

  有 \(\mathcal O(n\log n)\) 而且短得多的算法欸,问 Tiw 嘛 qwq。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <vector>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef long long LL;
#define int LL

template<typename Tp = int>
inline Tp rint() {
    Tp x = 0; int s = getchar();
    for ( ; s < '0' || '9' < s; s = getchar() );
    for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
    return x;
}

template<typename Tp>
inline void wint( Tp x ) {
    if ( x < 0 ) putchar( '-' ), x = -x;
    if ( 9 < x ) wint( x / 10 );
    putchar( x % 10 ^ '0' );
}

inline LL lmin( const LL a, const LL b ) { return a < b ? a : b; }

const int MAXN = 2.5e5;
const LL LINF = 1ll << 60;
int n, m, q;
std::vector<int> allq;

struct Event {
    int a, b, c; LL d;
    inline void read() {
        if ( int op = rint(); op == 1 ) {
            a = rint(), b = rint(), c = rint(), d = rint();
        } else if ( op == 2 ) {
            a = -1, b = rint(), c = rint(), d = rint();
        } else {
            a = b = -2, c = rint(), d = rint<LL>();
        }
    }
} evt[MAXN + 5];

struct SegmentTree {
    LL tag[MAXN << 2];
    
    inline void clear( const int u, const int l, const int r ) {
        tag[u] = 0;
        if ( l == r ) return ;
        int mid = l + r >> 1;
        clear( u << 1, l, mid ), clear( u << 1 | 1, mid + 1, r );
    }

    inline void modify( const int u, const int l, const int r,
      const int ml, const int mr, const LL v ) {
        if ( ml <= l && r <= mr ) return void( tag[u] += v );
        int mid = l + r >> 1;
        if ( ml <= mid ) modify( u << 1, l, mid, ml, mr, v );
        if ( mid < mr ) modify( u << 1 | 1, mid + 1, r, ml, mr, v );
    }

    inline LL query( const int u, const int l, const int r, const int x ) {
        if ( l == r ) return tag[u];
        int mid = l + r >> 1;
        if ( x <= mid ) return tag[u] + query( u << 1, l, mid, x );
        else return tag[u] + query( u << 1 | 1, mid + 1, r, x );
    }
} sgt; // It's for both Init and Solve.

namespace Init {

struct JiSegmentTree {
    LL tag1[MAXN << 2], tag2[MAXN << 2], mnv[MAXN << 2], smn[MAXN << 2];

    inline void clear( const int u, const int l, const int r ) {
        smn[u] = LINF;
        if ( l == r ) return ;
        int mid = l + r >> 1;
        clear( u << 1, l, mid ), clear( u << 1 | 1, mid + 1, r );
    }

    inline void pushad( const int u, const LL v1, const LL v2 ) {
        tag1[u] += v1, mnv[u] += v1;
        if ( smn[u] != LINF ) smn[u] += v2, tag2[u] += v2;
    }

    inline void pushdn( const int u ) {
        int a = mnv[u << 1], b = mnv[u << 1 | 1];
        if ( a <= b ) pushad( u << 1, tag1[u], tag2[u] );
        else pushad( u << 1, tag2[u], tag2[u] );
        if ( b <= a ) pushad( u << 1 | 1, tag1[u], tag2[u] );
        else pushad( u << 1 | 1, tag2[u], tag2[u] );
        tag1[u] = tag2[u] = 0;
    }

    inline void pushup( const int u ) {
        mnv[u] = lmin( mnv[u << 1], mnv[u << 1 | 1] );
        smn[u] = LINF;
        if ( mnv[u] < mnv[u << 1] ) smn[u] = lmin( smn[u], mnv[u << 1] );
        if ( mnv[u] < mnv[u << 1 | 1] )
            smn[u] = lmin( smn[u], mnv[u << 1 | 1] );
        if ( mnv[u] < smn[u << 1] ) smn[u] = lmin( smn[u], smn[u << 1] );
        if ( mnv[u] < smn[u << 1 | 1] )
            smn[u] = lmin( smn[u], smn[u << 1 | 1] );
    }

    inline void modify( const int u, const int l, const int r,
      const int ml, const int mr, const LL v ) {
        if ( ml <= l && r <= mr ) return pushad( u, v, v );
        int mid = l + r >> 1; pushdn( u );
        if ( ml <= mid ) modify( u << 1, l, mid, ml, mr, v );
        if ( mid < mr ) modify( u << 1 | 1, mid + 1, r, ml, mr, v );
        pushup( u );
    }

    inline void upto( const int u, const int l, const int r,
      const int ul, const int ur, const LL v ) {
        if ( mnv[u] >= v ) return ;
        if ( ul <= l && r <= ur && v < smn[u] )
            return pushad( u, v - mnv[u], 0 );
        int mid = l + r >> 1; pushdn( u );
        if ( ul <= mid ) upto( u << 1, l, mid, ul, ur, v );
        if ( mid < ur ) upto( u << 1 | 1, mid + 1, r, ul, ur, v );
        pushup( u );
    }

    inline LL query( const int u, const int l, const int r, const int x ) {
        if ( l == r ) return mnv[u];
        int mid = l + r >> 1; pushdn( u );
        if ( x <= mid ) return query( u << 1, l, mid, x );
        else return query( u << 1 | 1, mid + 1, r, x );
    }
} jsgt;

inline void init() {
    jsgt.clear( 1, 1, n );

    rep ( i, 1, q ) {
        if ( evt[i].a >= 0 ) {
            sgt.modify( 1, 1, n, evt[i].a, evt[i].b, evt[i].d );
            jsgt.modify( 1, 1, n, evt[i].a, evt[i].b, evt[i].d );
        } else if ( evt[i].a == -1 ) {
            jsgt.modify( 1, 1, n, evt[i].b, evt[i].c, -evt[i].d );
            jsgt.upto( 1, 1, n, evt[i].b, evt[i].c, 0 );
        } else {
            allq.push_back( i );
            evt[i].d += sgt.query( 1, 1, n, evt[i].c )
              - jsgt.query( 1, 1, n, evt[i].c );
        }
    }
}

} // namespace Init.

namespace Solve {

int ans[MAXN + 5];

inline void divide( const int l, const int r, const std::vector<int>& qvec ) {
    if ( qvec.empty() ) return ;
    if ( l == r ) {
        for ( int q: qvec ) ans[q] = l;
        return ;
    }
    
    int mid = l + r >> 1;
    rep ( i, l, mid ) if ( evt[i].a >= 0 ) {
        sgt.modify( 1, 1, n, evt[i].a, evt[i].b, evt[i].d );
    }

    std::vector<int> qlef, qrig;
    for ( int q: qvec ) {
        if ( sgt.query( 1, 1, n, evt[q].c ) >= evt[q].d ) qlef.push_back( q );
        else qrig.push_back( q );
    }

    divide( mid + 1, r, qrig );
    rep ( i, l, mid ) if ( evt[i].a >= 0 ) {
        sgt.modify( 1, 1, n, evt[i].a, evt[i].b, -evt[i].d );
    }

    divide( l, mid, qlef );
}

inline void solve() {
    sgt.clear( 1, 1, n );
    divide( 1, q + 1, allq );
    rep ( i, 1, q ) if ( evt[i].a == -2 ) {
        wint( ans[i] > i ? 0 : evt[ans[i]].c ), putchar( '\n' );
    }
}

} // namespace Solve.

signed main() {
    n = rint(), m = rint(), q = rint();
    rep ( i, 1, q ) evt[i].read();

    Init::init();
    Solve::solve();
    return 0;
}

posted @ 2021-06-21 19:23  Rainybunny  阅读(107)  评论(0编辑  收藏  举报