zoukankan      html  css  js  c++  java
  • Solution -「JOISC 2021」「LOJ #3489」饮食区

    (mathcal{Description})

      Link.

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

    (mathcal{Solution})

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

      ——简单整体二分。

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

      ——吉司机线段树。

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

      有 (mathcal O(nlog 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( '
    ' );
        }
    }
    
    } // namespace Solve.
    
    signed main() {
        n = rint(), m = rint(), q = rint();
        rep ( i, 1, q ) evt[i].read();
    
        Init::init();
        Solve::solve();
        return 0;
    }
    
    
  • 相关阅读:
    005 Stream的创建
    006 虚拟主机
    002 nginx的进程模型
    001 胡说八道
    001 nginx的简介和安装
    004 docker配置国内镜像站
    012 SSH
    发放失败,此请求可能存在风险,已被微信拦截【未解决】
    项目使用Nuget,然后SVN checkout后显示缺少引用
    使用存储过程非常慢,但是直接执行SQL很快
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14915294.html
Copyright © 2011-2022 走看看