Submission #16871209


Source Code Expand

/**
 * Dont raise your voice, improve your argument.
 * --Desmond Tutu
 */

#include <bits/stdc++.h>
using namespace std;

const bool ready = [](){
    ios_base::sync_with_stdio(false); cin.tie(0);
    cout << fixed << setprecision(12);
    return true;
}();

const double PI = acos(-1);
using ll= long long;
#define int ll
#define all(v) (v).begin(), (v).end()
#define fori(n) for(int i=0; i<int(n); i++)

#define cini(i) int i; cin>>i;
#define cins(s) string s; cin>>s;
#define cind(d) double d; cin>>d;
#define cinai(a,n) vi a(n); fori(n) { cin>>a[i]; }
#define cinas(s,n) vs s(n); fori(n) { cin>>s[i]; }
#define cinad(a,n) vd a(n); fori(n) { cin>>a[i]; }

using pii= pair<int, int>;
using pdd= pair<double, double>;
using vd= vector<double>;
using vb= vector<bool>;
using vi= vector<int>;
using vvi= vector<vi>;
using vs= vector<string>;

#define endl "\n"


template<typename E>
struct SegmentTreeLazy {
    vector<E> data;
    vector<E> lazyInc;
    vector<bool> lazyIncB;  /* flag if there is a pending lazyInc in node */
    vector<E> lazySet;
    vector<bool> lazySetB;  /* flag if there is a pending lazySet in node */

    E neutral;
    int n;

    function<E(E,E)> plus;
    function<E(E,int)> mult;

    SegmentTreeLazy(int _n, E _neutral) {
        n=1;
        while(n<_n)
            n*=2;

        data.resize(n*2, _neutral);
        lazyInc.resize(n*2, _neutral);
        lazyIncB.resize(n*2);
        lazySet.resize(n*2, _neutral);
        lazySetB.resize(n*2);
        neutral=_neutral;
    }

    /* bulk update in O(n) */
    template<typename Iterator>
    void init(Iterator beg, Iterator end) {
        for(int idx=n; beg!=end; beg++, idx++)
            data[idx]=*beg;

        for(int idx=n-1; idx>=1; idx--)
            data[idx]=plus(data[idx*2], data[idx*2+1]);
    }

    /* pushes down the pending updates to the vertex node 
     * If both lazies are set then the inc was later, so both
     * have to be pushed.
     * But first the set, which erases all previously set 
     * and inc on the child nodes, then the inc.
     * */
    void pushlazy(int node, int sL, int sR) {
        if(lazySetB[node]) {
            //cerr<<"pushlazy Set, node="<<node<<" sL="<<sL<<" sR="<<sR<<endl;

            if(sL!=sR) {
                int mid=(sL+sR)/2;
                rangeSet(node*2, sL   , mid, sL   , mid, lazySet[node]);
                rangeSet(node*2+1, mid+1, sR , mid+1, sR , lazySet[node]);
            }

            lazySetB[node]=false;
            lazySet[node]=neutral;
        }

        if(lazyIncB[node]) {
            //cerr<<"pushlazy Inc, node="<<node<<" sL="<<sL<<" sR="<<sR<<endl;
            if(sL!=sR) {
                int mid=(sL+sR)/2;
                rangeInc(node*2, sL   , mid, sL   , mid, lazyInc[node]);
                rangeInc(node*2+1, mid+1, sR , mid+1, sR , lazyInc[node]);
            }
            lazyIncB[node]=false;
            lazyInc[node]=neutral;
        }
    }

    /* @return accumulative (l,r), both inclusive, top down */
    E query(int node, int sL, int sR, int l, int r) {
        if (r < sL || l > sR)
            return neutral;
        //cerr<<"query, node="<<node<<" sL="<<sL<<" sR="<<sR<<" l="<<l<<" r="<<r<<" data[node]="<<data[node]<<endl;

        if (l<=sL && r>=sR)
            return data[node];

        pushlazy(node, sL, sR);

        int mid = (sL+sR)/2;
        return plus(query(node*2, sL, mid, l, r), query(node*2+1, mid+1, sR, l, r));
    }
    E query(int l, int r) {
        return query(1, 0, n-1, l, r);
    }

    /* set all position in (l,r) to val */
    void rangeSet(int node, int sL, int sR, int l, int r, E val) {
        if (r < sL || l > sR)
            return;
        //cerr<<"rangeSet node="<<node<<" sL="<<sL<<" sR="<<sR<<" l="<<l<<" r="<<r<<" val="<<val<<endl;

        if(l<=sL && r>=sR) {
            lazySet[node]=val;
            lazyInc[node]=neutral;
            lazySetB[node]=true;
            lazyIncB[node]=false;
            data[node]=mult(val, sR-sL+1);
            //cerr<<"rangeSet did set node="<<data[node]<<endl;
            return;
        }

        pushlazy(node, sL, sR);

        int mid = (sL+sR)/2;
        rangeSet(node*2  , sL   , mid, l, r, val);
        rangeSet(node*2+1, mid+1, sR , l, r, val);
        data[node]=plus(data[node*2], data[node*2+1]);
    }

    /* set val at positions (l,r) */
    void rangeSet(int l, int r, E val) {
        rangeSet(1, 0, n-1, l, r, val);
    }

    /* increment all position in (l,r) by inc */
    void rangeInc(int node, int sL, int sR, int l, int r, E inc) {
        if (r < sL || l > sR)
            return;
        //cerr<<"rangeInc node="<<node<<" sL="<<sL<<" sR="<<sR<<" l="<<l<<" r="<<r<<" val="<<inc<<endl;

        if(l<=sL && r>=sR) {
            lazyInc[node]+=inc;
            lazyIncB[node]=true;
            data[node]+=mult(inc, sR-sL+1);
            //cerr<<"rangeInc did set node="<<data[node]<<endl;
            return;
        }

        pushlazy(node, sL, sR);

        int mid = (sL+sR)/2;
        rangeInc(node*2  , sL   , mid, l, r, inc);
        rangeInc(node*2+1, mid+1, sR , l, r, inc);
        data[node]=plus(data[node*2], data[node*2+1]);
    }

    /* increment by inc at positions (l,r) */
    void rangeInc(int l, int r, E inc) {
        rangeInc(1, 0, n-1, l, r, inc);
    }
};

/* some wiered dp...
 *
 *
 */
void solve() {
    cini(n);
    cini(k);
    vi l(k);
    vi r(k);
    for(int i=0; i<k; i++) 
        cin>>l[i]>>r[i];

    const int MOD=998244353;
    SegmentTreeLazy<int> seg(n+1, 0);
    seg.plus=[](int i1, int i2) { return (i1+i2)%MOD; };
    seg.mult=[](int i1, int i2) { return (i1*i2)%MOD; };

    seg.rangeSet(1,1,1);

    for(int i=0; i<n; i++) {
        const int val=seg.query(i,i);
        if(val==0)
            continue;

        for(int j=0; j<k; j++)
            seg.rangeInc(i+l[j], i+r[j], val);
    }

    int ans=seg.query(n, n);
    cout<<ans<<endl;

}

signed main() {
    solve();
}

// FIRST THINK, THEN CODE
// DO NOT JUMP BETWEEN PROBLEMS

Submission Info

Submission Time
Task D - Leaping Tak
User spookywooky
Language C++ (GCC 9.2.1)
Score 400
Code Size 6222 Byte
Status AC
Exec Time 851 ms
Memory 15868 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 400 / 400
Status
AC × 4
AC × 28
Set Name Test Cases
Sample s1.txt, s2.txt, s3.txt, s4.txt
All 01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, 19.txt, 20.txt, 21.txt, 22.txt, 23.txt, 24.txt, s1.txt, s2.txt, s3.txt, s4.txt
Case Name Status Exec Time Memory
01.txt AC 7 ms 3524 KiB
02.txt AC 3 ms 3576 KiB
03.txt AC 2 ms 3524 KiB
04.txt AC 3 ms 3616 KiB
05.txt AC 4 ms 3472 KiB
06.txt AC 3 ms 3672 KiB
07.txt AC 2 ms 3564 KiB
08.txt AC 2 ms 3588 KiB
09.txt AC 2 ms 3628 KiB
10.txt AC 2 ms 3600 KiB
11.txt AC 2 ms 3636 KiB
12.txt AC 420 ms 15684 KiB
13.txt AC 66 ms 15844 KiB
14.txt AC 109 ms 15572 KiB
15.txt AC 68 ms 15868 KiB
16.txt AC 481 ms 15796 KiB
17.txt AC 686 ms 15696 KiB
18.txt AC 851 ms 15784 KiB
19.txt AC 555 ms 15692 KiB
20.txt AC 363 ms 15800 KiB
21.txt AC 66 ms 15696 KiB
22.txt AC 70 ms 15816 KiB
23.txt AC 71 ms 15800 KiB
24.txt AC 69 ms 15760 KiB
s1.txt AC 8 ms 3532 KiB
s2.txt AC 3 ms 3660 KiB
s3.txt AC 11 ms 3656 KiB
s4.txt AC 2 ms 3656 KiB