1 条题解

  • 0
    @ 2026-9-19 23:12:20

    考虑维护两个数组 lstrlst_rcntrcnt_r,分别表示 rr 这个点从哪个时刻开始连续接受别人浇水,以及在 lstrlst_r 之前累计被浇水多少次。

    对于时刻 ii 的修改操作,显然只有 r1r - 1rrlstlstcntcnt 会改变,其他点不受影响。不妨分讨两边的变化情况:如果原来被浇水但现在不浇了,则可以令 cntrcntr+(ilstr+1)cnt_r \leftarrow cnt_r + (i - lst_r + 1),表示把这段时间的浇水量累计存下,然后再令 lstr=d+1lst_r = d + 1 表示从来没有被连续浇过水即可;如果原来没被浇水但现在被浇,则直接令 lstr=i+1lst_r = i + 1 表示第二天起开始接受浇水即可。

    对于查询,可以分成 lstrlst_r 之前和之后两部分。前者的贡献显然是 cntrcnt_r,后者的贡献显然是 ilstr+1i - lst_r + 1,加起来即可。

    注意我们使用 lstr=d+1lst_r = d + 1 表示 rr 暂时没有被楼上的人浇水,因此使用 ilstr+1i - lst_r + 1 时应当将其对 00max\max

    :::info[参考代码]

    #include<bits/stdc++.h>
    // #define int long long
    #define fo(i, l, r) for(decltype((l) + (r)) i = (l); i <= (r); ++i)
    #define fd(i, l, r) for(decltype((l) + (r)) i = (l); i >= (r); --i)
    #define fu(i, l, r) for(decltype((l) + (r)) i = (l); i <  (r); ++i)
    #define y1 zhang_kevin
    #define pii pair<int, int>
    #define fi first
    #define se second
    #define vec vector
    #define pb push_back
    #define eb emplace_back
    #define all(v) v.begin(), v.end()
    #define ll long long
    #define ull unsigned long long
    #define flush() (fwrite(obuf, 1, p3 - obuf, stdout), p3 = obuf)
    using namespace std;
    bool ST;
    char ibuf[1 << 20], *p1 = ibuf, *p2 = ibuf, obuf[1 << 20], *p3 = obuf;
    inline char gc(){
        if(p1 == p2){
            p1 = ibuf, p2 = ibuf + fread(ibuf, 1, 1 << 20, stdin);
            if(p1 == p2) return EOF;
            return *p1++;
        }
        return *p1++;
    }
    inline char pc(char ch){
        if(p3 == obuf + (1 << 20)) flush();
        *p3 = ch;
        return *p3++;
    }
    template<typename type>
    inline int rd(type &x){
        x = 0; bool f = 0; char ch = gc();
        while(!isdigit(ch)) f |= ch == '-', ch = gc();
        while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
        return f ? x = -x : 0;
    }
    template<typename type, typename ...T>
    inline void rd(type &x, T &...y){rd(x), rd(y...);}
    inline void gs(string &s){
        s.clear(); char c = gc();
        while(c == ' ' || c == '\n' || c == '\t' || c == '\r') c = gc();
        while(c != ' ' && c != '\n' && c != '\t' && c != '\r' && c != EOF) s += c, c = gc();
        return;
    }
    class Flush{public: ~Flush(){flush();}}___;
    template<typename type>
    inline void wr(type x){
        if(x < 0) pc('-'), x = -x;
        if(x > 9) wr(x / 10);
        pc(x % 10 + '0');
        return;
    }
    inline void wrs(const string& s){for(auto ch : s) pc(ch);}
    namespace Solution{
        int n, d, a[200005], lst[200005], cnt[200005];
        inline void Solve(){
            rd(n, d); fo(i, 1, n) rd(a[i]), lst[i - 1] = a[i] < a[i - 1] ? 1 : d + 1;
            fo(i, 1, d){
                char ch = gc(); while(ch != '!' && ch != '?') ch = gc();
                if(ch == '!'){
                    int r, x; rd(r, x), r++;
                    if(r > 1 && a[r - 1] > x){
                        if(a[r - 1] <= a[r]){
                            lst[r - 1] = i + 1;
                        }
                    }else if(r > 1 && a[r - 1] <= x){
                        if(a[r - 1] > a[r]){
                            cnt[r - 1] += max(i - lst[r - 1] + 1, 0);
                            lst[r - 1] = d + 1;
                        }
                    }
                    if(r < n && a[r + 1] < x){
                        if(a[r + 1] >= a[r]){
                            lst[r] = i + 1;
                        }
                    }else if(r < n && a[r + 1] >= x){
                        if(a[r + 1] < a[r]){
                            cnt[r] += max(i - lst[r] + 1, 0);
                            lst[r] = d + 1;
                        }
                    }
                    a[r] = x;
                }else{
                    int r; rd(r);
                    wr(max(i - lst[r] + 1, 0) + cnt[r]), pc('\n');
                }
                // cerr << cnt[1] << '\n';
            }
            return;
        }
    }
    bool ED;
    signed main(){
        clock_t START = clock();
        // freopen("input.in", "r", stdin), freopen("output.out", "w", stdout);
        Solution::Solve();
        cerr << (double)(clock() - START) / CLOCKS_PER_SEC << " s" << '\n';
        cerr << 1.0 * abs(&ED - &ST) / 1024 / 1024 << " MB" << '\n';
        return 0;
    }
    

    :::

    • 1

    [EGOI 2026] 给花浇水 / Watering Plants

    信息

    ID
    12690
    时间
    2000ms
    内存
    1124MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者