Submission #597890

#TimeUsernameProblemLanguageResultExecution timeMemory
597890qwerasdfzxclFish 2 (JOI22_fish2)C++14
100 / 100
2236 ms23296 KiB
#include <bits/stdc++.h>

typedef long long ll;
using namespace std;
int n, a[100100];

struct Seg1{
    ll tree[200200], sz;
    void init(int n){
        sz = n;
        for (int i=sz;i<sz*2;i++) tree[i] = a[i-sz];
        for (int i=sz-1;i;i--) tree[i] = tree[i<<1] + tree[i<<1|1];
    }
    void update(int p, int x){
        for (tree[p+=sz]=x;p>1;p>>=1) tree[p>>1] = tree[p] + tree[p^1];
    }
    ll query(int l, int r){
        ++r;
        ll ret = 0;
        for (l+=sz, r+=sz;l<r;l>>=1, r>>=1){
            if (l&1) ret += tree[l++];
            if (r&1) ret += tree[--r];
        }
        return ret;
    }
}tree1;

struct Seg2{
    int tree[400400];
    void init(int i, int l, int r){
        if (l==r) {tree[i] = a[l]; return;}
        int m = (l+r)>>1;
        init(i<<1, l, m); init(i<<1|1, m+1, r);
        tree[i] = max(tree[i<<1], tree[i<<1|1]);
    }
    void update(int i, int l, int r, int p, int x){
        if (p<l || r<p) return;
        if (l==r) {tree[i] = x; return;}
        int m = (l+r)>>1;
        update(i<<1, l, m, p, x); update(i<<1|1, m+1, r, p, x);
        tree[i] = max(tree[i<<1], tree[i<<1|1]);
    }
    int left_bound(int i, int l, int r, int s, int e, ll x){
        if (r<s || e<l) return -1;
        if (tree[i] <= x) return -1;
        if (l==r) return l;

        int m = (l+r)>>1;
        int tmp = left_bound(i<<1|1, m+1, r, s, e, x);
        if (tmp!=-1) return tmp;
        return left_bound(i<<1, l, m, s, e, x);
    }
    int right_bound(int i, int l, int r, int s, int e, ll x){
        if (r<s || e<l) return -1;
        if (tree[i] <= x) return -1;
        if (l==r) return l;

        int m = (l+r)>>1;
        int tmp = right_bound(i<<1, l, m, s, e, x);
        if (tmp!=-1) return tmp;
        return right_bound(i<<1|1, m+1, r, s, e, x);
    }
}tree2;

struct Node{
    int mn, cnt;
    Node(){}
    Node(int _mn, int _cnt): mn(_mn), cnt(_cnt) {}
    Node operator + (const Node &N) const{
        if (mn < N.mn) return *this;
        if (mn > N.mn) return N;
        return Node(mn, cnt+N.cnt);
    }
};

struct Seg3{
    Node tree[400400];
    int lazy[400400];
    void init(int i, int l, int r){
        if (l==r) {tree[i] = Node(0, 1); return;}
        int m = (l+r)>>1;
        init(i<<1, l, m); init(i<<1|1, m+1, r);
        tree[i] = tree[i<<1] + tree[i<<1|1];
    }
    void propagate(int i, int l, int r){
        tree[i].mn += lazy[i];
        if (l!=r){
            lazy[i<<1] += lazy[i];
            lazy[i<<1|1] += lazy[i];
        }
        lazy[i] = 0;
    }
    void update(int i, int l, int r, int s, int e, int x){
        propagate(i, l, r);
        if (r<s || e<l) return;
        if (s<=l && r<=e){
            lazy[i] += x;
            propagate(i, l, r);
            return;
        }
        int m = (l+r)>>1;
        update(i<<1, l, m, s, e, x); update(i<<1|1, m+1, r, s, e, x);
        tree[i] = tree[i<<1] + tree[i<<1|1];
    }
    Node query(int i, int l, int r, int s, int e){
        propagate(i, l, r);
        if (r<s || e<l) return Node(1e9, 0);
        if (s<=l && r<=e) return tree[i];
        int m = (l+r)>>1;
        return query(i<<1, l, m, s, e) + query(i<<1|1, m+1, r, s, e);
    }
}tree3;

struct Seg4{
    vector<pair<int, int>> tree[400400];
    void update(int i, int l, int r, int s, int e){
        if (l==r) {
            tree[i].emplace_back(s, e);
            tree3.update(1, 1, n, s, e, 1);
            return;
        }

        int m = (l+r)>>1;
        if (e<=m) update(i<<1, l, m, s, e);
        else if (m+1<=s) update(i<<1|1, m+1, r, s, e);
        else{
            tree[i].emplace_back(s, e);
            tree3.update(1, 1, n, s, e, 1);
        }
    }
    void erase(int i, int l, int r, int p){
        while(!tree[i].empty() && tree[i].back().first <= p && p <= tree[i].back().second){
            tree3.update(1, 1, n, tree[i].back().first, tree[i].back().second, -1);
            tree[i].pop_back();
        }
        if (l==r) return;

        int m = (l+r)>>1;
        if (p<=m) erase(i<<1, l, m, p);
        else erase(i<<1|1, m+1, r, p);
    }
    void debug(int i, int l, int r){
        printf("[%d, %d]: ", l, r);
        for (auto &[x, y]:tree[i]) printf("[%d, %d] / ", x, y);
        printf("\n");
        if (l==r) return;

        int m = (l+r)>>1;
        debug(i<<1, l, m);
        debug(i<<1|1, m+1, r);
    }
}tree4;

bool cmp(pair<int, int> &x, pair<int, int> &y){return x.second-x.first < y.second-y.first;}

bool ok(int l, int r, int s, int e){
    ll L = s==l?1e18:a[s-1], R = e==r?1e18:a[e+1];
    ll S = tree1.query(s, e);
    return S<L && S<R;
}

vector<int> getL(int l, int r, int s){
    vector<int> ret;
    int cur = s;
    while(true){
        int nxt = tree2.left_bound(1, 1, n, l, cur-1, tree1.query(cur, s));
        if (nxt==-1) break;
        ret.push_back(nxt+1);
        cur = nxt;
    }

    ret.push_back(l);
    return ret;
}

vector<int> getR(int l, int r, int s){
    vector<int> ret;
    int cur = s;
    while(true){
        int nxt = tree2.right_bound(1, 1, n, cur+1, r, tree1.query(s, cur));
        if (nxt==-1) break;
        //printf(" %d %d -> %d\n", s, cur, nxt);
        ret.push_back(nxt-1);
        cur = nxt;
    }
    ret.push_back(r);
    return ret;
}

void refresh(int x, vector<pair<int, int>> &P){
    if (x<1 || x>n) return;
    tree4.erase(1, 1, n, x);
    auto L = getL(1, n, x);
    auto R = getR(1, n, x);


    for (auto &l:L){
        for (auto &r:R) if (ok(1, n, l, r)){
            P.emplace_back(l, r);
        }
    }
}

void update(int x, int y){
    tree1.update(x, y);
    tree2.update(1, 1, n, x, y);
    a[x] = y;

    vector<pair<int, int>> P;
    refresh(x-1, P);
    refresh(x, P);
    refresh(x+1, P);

    sort(P.begin(), P.end(), cmp);
    P.erase(unique(P.begin(), P.end()), P.end());
    for (auto &[l, r]:P) tree4.update(1, 1, n, l, r);

    //tree4.debug(1, 1, n);
}

int query(int l, int r){
    auto R0 = getR(l, r-1, l);
    auto L0 = getL(l+1, r, r);

    int nl = l, nr = r;
    for (auto &x:R0) if (ok(l, r, l, x)) nl = x+1;
    for (auto &x:L0) if (ok(l, r, x, r)) nr = x-1;

    return tree3.query(1, 1, n, nl, nr).cnt;
}

int main(){
    scanf("%d", &n);
    for (int i=1;i<=n;i++) scanf("%d", a+i);

    tree1.init(n+1);
    tree2.init(1, 1, n);
    tree3.init(1, 1, n);

    vector<pair<int, int>> P;
    for (int i=1;i<=n;i++){
        //printf("ok %d\n", i);
        auto R = getR(1, n, i);
        for (auto &x:R) if (ok(1, n, i, x)){
            P.emplace_back(i, x);
            //printf("%d %d\n", i, x);
        }
    }
    sort(P.begin(), P.end(), cmp);
    for (auto &[l, r]:P) tree4.update(1, 1, n, l, r);

    //tree4.debug(1, 1, n);

    int q;
    scanf("%d", &q);
    while(q--){
        int op, x, y;
        scanf("%d %d %d", &op, &x, &y);
        if (op==1) update(x, y);
        else printf("%d\n", query(x, y));
    }
    return 0;
}

Compilation message (stderr)

fish2.cpp: In member function 'void Seg4::debug(int, int, int)':
fish2.cpp:144:20: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  144 |         for (auto &[x, y]:tree[i]) printf("[%d, %d] / ", x, y);
      |                    ^
fish2.cpp: In function 'void update(int, int)':
fish2.cpp:216:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  216 |     for (auto &[l, r]:P) tree4.update(1, 1, n, l, r);
      |                ^
fish2.cpp: In function 'int main()':
fish2.cpp:250:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  250 |     for (auto &[l, r]:P) tree4.update(1, 1, n, l, r);
      |                ^
fish2.cpp:233:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  233 |     scanf("%d", &n);
      |     ~~~~~^~~~~~~~~~
fish2.cpp:234:33: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  234 |     for (int i=1;i<=n;i++) scanf("%d", a+i);
      |                            ~~~~~^~~~~~~~~~~
fish2.cpp:255:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  255 |     scanf("%d", &q);
      |     ~~~~~^~~~~~~~~~
fish2.cpp:258:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  258 |         scanf("%d %d %d", &op, &x, &y);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...