1 条题解

  • 0
    @ 2025-8-24 22:11:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar zuytong
    且将新火试新茶,诗酒趁年华

    搬运于2025-08-24 22:11:41,当前版本为作者最后更新于2022-09-07 09:35:19,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    思路

    我们考虑开一棵线段树,表示区间 [l,r][l,r] 最后一次操作 2 的时间戳

    对于操作 1:我们交换树上 xxyy 两点的值。

    对于操作 2:我们进行区间 [l,r][l,r] 赋值。

    对于操作 3:我们查询树上 xx 点的值,并记录为 tit_i

    考虑将所有的询问离线下来,对 rr 做扫描线:遇到操作 3 时,我们在 tit_i 的位置加上 val[ti]val[t_i] 并更新前缀和;对于询问 [l,r][l,r],我们查询 ll 的后缀和,这个可以通过树状数组实现。

    由于 n,m,qn,m,q 同阶,时间复杂度为 O(nlogn)O(n\log n)


    代码

    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #define LL long long
    #define FOR(i, x, y) for(int i = (x); i <= (y); i++)
    #define ROF(i, x, y) for(int i = (x); i >= (y); i--)
    #define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
    inline int reads()
    {
        int sign = 1, re = 0; char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
        while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
        return sign * re;
    }
    int n, m, q;
    int ty[1000005], x[1000005], y[1000005], val[1000005];
    int tr[4000005];
    #define ls (now << 1)
    #define rs ((now << 1) | 1)
    inline void down(int now)
    {
        if(tr[now])
        {
            tr[ls] = tr[rs] = tr[now];
            tr[now] = 0;
        }
    }
    void modify(int now, int l, int r, int L, int R, int ti)
    {
        if(L <= l && r <= R) return void(tr[now] = ti);
        down(now); int mid = (l + r) >> 1;
        if(L <= mid) modify(ls, l, mid, L, R, ti);
        if(mid < R) modify(rs, mid + 1, r, L, R, ti);
    }
    int query(int now, int l, int r, int to)
    {
        if(l == r) return tr[now];
        if(tr[now]) return tr[now];
        int mid = (l + r) >> 1;
        if(to <= mid) return query(ls, l, mid, to);
        else return query(rs, mid + 1, r, to);
    }
    LL sum[1000005];
    inline int lb(int x) {return x & (-x);}
    inline void add(int x, int val)
    {
        if(!x) return;
        while(x <= m)
            sum[x] += val,
            x += lb(x);
    }
    inline LL get_sum(int x)
    {
        if(x < 1) return 0;
        LL re = 0;
        while(x)
            re += sum[x],
            x ^= lb(x);
        return re;
    }
    #define pii std::pair<int, int>
    #define mp std::make_pair
    std::vector<pii> qst[1000005];
    LL ans[1000005];
    signed main()
    {
    #ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
        freopen("test.out", "w", stdout);
    #endif
        n = reads(), m = reads(), q = reads();
        FOR(i, 1, m)
        {
            ty[i] = reads();
            if(ty[i] == 1)
            {
                x[i] = reads(), y[i] = reads();
                int vx = query(1, 1, n, x[i]), vy = query(1, 1, n, y[i]);
                modify(1, 1, n, x[i], x[i], vy), modify(1, 1, n, y[i], y[i], vx);
            }
            else if(ty[i] == 2)
            {
                x[i] = reads(), y[i] = reads(), val[i] = reads();
                modify(1, 1, n, x[i], y[i], i);
            }
            else
            {
                x[i] = reads();
                y[i] = query(1, 1, n, x[i]);
            }
        }
        FOR(i, 1, q)
        {
            int l = reads(), r = reads();
            qst[r].emplace_back(mp(l, i));
        }
        FOR(i, 1, m)
        {
            if(ty[i] == 3) add(y[i], val[y[i]]);
            for(pii j : qst[i]) ans[j.second] = get_sum(i) - get_sum(j.first - 1);
        }
        FOR(i, 1, q) printf("%lld\n", ans[i]);
        return 0;
    }
    
    • 1

    信息

    ID
    8028
    时间
    1000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者