1 条题解

  • 0
    @ 2025-8-24 22:51:04

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Fire_flame
    乐观乐观再乐观

    搬运于2025-08-24 22:51:04,当前版本为作者最后更新于2023-06-12 23:36:51,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    前置知识:T4 五五五五 (Easy) 正解(必须),线段树或者平衡树。

    可以发现上一道题其实提示了这个题目的方法呢。

    Method1\mathbf{Method1}

    本方法考虑线段树维护,定义 gig_i 表示数组 a1a2ai\overline{a_1a_2\dots a_i} 末尾连续 55 的个数。

    首先预处理 gg 数组和初始答案 ansans

    不难发现,在进行操作 11 的过程中,仅仅维护 gg 数组是不够的,我们需要预处理一个镜像数组 gg',一个镜像答案 ansans'

    gig'_i 表示 aia(i1)a1\overline{a_ia_{(i-1)}\dots a_1} 末尾连续 55 的个数。接下来,我们用线段树维护 g,gg,g' 即可。


    对于操作 11,我们得分类讨论:

    • 如果是把一个 55 改成其他的数,那么 ggxgx1g_{g'_{x}} \sim g_{x-1} 全部减 gxg_xgxg_x 清零。

      并且 ggxgx1g'_{g_{x}} \sim g'_{x-1} 全部减 gxg'_xgxg'_x 清零。

    • 把其他的数改成 55 也同理,这里不再赘述。

    记得每一次操作完 ans,ansans,ans' 都要相应的改变。


    对于操作 22,我们使用一个变量 nownow 表示经过翻转了奇数次还是偶数次,now=1now=1 表示翻转了奇数次,now=0now=0 表示翻转了偶数次。

    操作 22 时直接异或一下 nownow 即可。


    对于操作 33,如果 now=0now=0 输出 ansans,否则输出 ansans'


    对于操作 44,就是一个普通线段树的区间求和(看这出题人多良心)。

    标程:

    #include <ctime>//By wzy2021   (Orz Orz)
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    
    struct node {
    	int l, r, sz, sum;
    	int l5, r5, s5; ll sf, sg; 
    };
    int n, m; ll f[N], g[N];
    
    void init (int n) {
    	for (int i = 1; i <= n; ++i) f[i] = (f[i - 1] + i) % mod, g[i] = (g[i - 1] + i * (i + 1) / 2) % mod;
    }
    
    int get (int x, int y) {
    	return (1ll * f[x] * y % mod + g[x]) % mod;
    }
    
    struct Tree {
    	node t[N << 2];
    	void pushup (int x) {
    		t[x].sum = t[x << 1].sum + t[x << 1 | 1].sum;
    		t[x].l5 = t[x << 1].l5; if (t[x << 1].l5 == t[x << 1].sz) t[x].l5 += t[x << 1 | 1].l5;
    		t[x].r5 = t[x << 1 | 1].r5; if (t[x << 1 | 1].r5 == t[x << 1 | 1].sz) t[x].r5 += t[x << 1].r5;
    		t[x].s5 = ((t[x << 1].s5 + t[x << 1 | 1].s5 - f[t[x << 1].r5] - f[t[x << 1 | 1].l5] + f[t[x << 1].r5 + t[x << 1 | 1].l5]) % mod + mod) % mod;
    		t[x].sf = (t[x << 1].sf + t[x << 1 | 1].sf + 1ll * t[x << 1].sz * t[x << 1 | 1].s5 % mod) % mod;
    		t[x].sf -= get (t[x << 1].r5, t[x << 1].sz - t[x << 1].r5) + get (t[x << 1 | 1].l5, t[x << 1].sz);
    		t[x].sf += get (t[x << 1].r5 + t[x << 1 | 1].l5, t[x << 1].sz - t[x << 1].r5);
    		t[x].sf = (t[x].sf % mod + mod) % mod;
    	}
    	void build (int x, int l, int r) {
    		t[x].l5 = t[x].r5 = t[x].s5 = t[x].sf = t[x].sg = 0;
    		t[x].l = l; t[x].r = r; t[x].sz = r - l + 1; t[x].sum = 0;
    		if (l == r) return ;
    		int mid = (l + r) >> 1;
    		build (x << 1, l, mid); build (x << 1 | 1, mid + 1, r);
    	}
    	void update (int x, int k, int v) {
    		if (t[x].l == t[x].r) {
    			t[x].sum = v; t[x].l5 = t[x].r5 = t[x].s5 = t[x].sf = t[x].sg = (v == 5);
    			return ;
    		}
    		int mid = (t[x].l + t[x].r) >> 1;
    		if (k <= mid) update (x << 1, k, v);
    		else update (x << 1 | 1, k, v);
    		pushup(x);
    	}
    	int query (int x, int l, int r) {
    		if (l <= t[x].l && t[x].r <= r) return t[x].sum;
    		int mid = (t[x].l + t[x].r) >> 1, ans = 0;
    		if (l <= mid) ans = (ans + query (x << 1, l, r)) % mod;
    		if (r > mid) ans = (ans + query (x << 1 | 1, l, r)) % mod;
    		return ans;
    	}
    } T[2]; 
    
    int main() {
    	init(N - 5);
    	int n, m; scanf ("%d%d", &n, &m);
    	T[0].build (1, 1, n); T[1].build(1, 1, n);
    	for (int i = 1; i <= n; ++i) {
    		int x; scanf ("%d", &x); T[0].update (1, i, x); T[1].update (1, n - i + 1, x); 
    	} int flag = 0;
    	while (m--) {
    		int opt; scanf ("%d", &opt);
    		if (opt == 1) {
    			int x, y; scanf ("%d%d", &x, &y);
    			T[flag].update(1, x, y); T[flag ^ 1].update(1, n - x + 1, y);
    		} else if (opt == 2) {
    			flag ^= 1;
    		} else if (opt == 3) {
    			printf ("%lld\n", T[flag].t[1].sf % mod);
    		} else {
    			int l, r; scanf ("%d%d", &l, &r);
    			printf ("%d\n", T[flag].query (1, l, r));
    		}
    	}
    	return 0;
    }
    

    Method2\mathbf{Method2}

    这个题目也可以用平衡树解决。

    因为 FF 不想再写字了,那么就留给大家去思考。

    • 1

    信息

    ID
    8777
    时间
    2500ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者