zoukankan      html  css  js  c++  java
  • 【JZOJ 1384】Alice的游戏

    题目大意:

    (n) 个数,(m) 个操作,每个操作都给定一个区间、两个步骤,查询区间和与区间加一(即 (0leq ileq 8)(ileftarrow i+1),否则 (ileftarrow 0))。

    正文:

    因为是区间操作所以考虑线段树。可以开两个线段树,一个存区间和,另一个存区间内(0ldots 9) 的数量。本题的难点主要在于 Lazy 标记,变形时建议开个工具数组。

    int tool[11];
    
    void spreadd(int x)
    {
    	for(int i = 0; i <= 9; i++)
    	{
    		tool[(i + sgt[x].dif) % 10] = val[x][i];
    	}
    	sgt[x].val = 0;
    	for(int i = 0; i <= 9; i++)
    	{
    		val[x][i] = tool[i];
    		sgt[x].val += val[x][i] * i;
    	}
    	sgt[x].dif = 0;
    }
    
    void spread(int x) {
    	if(sgt[x].lzy) {
    		sgt[x << 1].lzy += sgt[x].lzy;
    		sgt[x << 1 | 1].lzy += sgt[x].lzy;
    		sgt[x << 1].dif += sgt[x].lzy;
    		sgt[x << 1 | 1].dif += sgt[x].lzy;
    		sgt[x].lzy = 0;
    		spreadd(x << 1);
    		spreadd(x << 1 | 1);
    		spreadd(x);
    	}
    }
    
    

    全部代码:

    const int N = 250010;
    
    int n, m;
    int a[N];
    struct SegmentTree {
        int l, r;
        int val, lzy, dif;
    } sgt[N << 2];
    int val[N << 2][10];
    
    inline void opt(int x) {
        sgt[x].val = sgt[x << 1].val + sgt[x << 1 | 1].val;
        for(register int i = 0; i <= 9; ++i) {
            val[x][i] = val[x << 1][i] + val[x << 1 | 1][i];
        }
    }
    
    void build(int x, int l, int r) {
        sgt[x].l = l, sgt[x].r = r;
    
        if(l == r) {
            sgt[x].val = a[l];
            ++val[x][a[l]];
            return ;
        }
    
        int mid = (sgt[x].l + sgt[x].r) / 2;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        opt(x);
    }
    
    int tool[11];
    
    void spreadd(int x)
    {
    	for(int i = 0; i <= 9; i++)
    	{
    		tool[(i + sgt[x].dif) % 10] = val[x][i];
    	}
    	sgt[x].val = 0;
    	for(int i = 0; i <= 9; i++)
    	{
    		val[x][i] = tool[i];
    		sgt[x].val += val[x][i] * i;
    	}
    	sgt[x].dif = 0;
    }
    
    void spread(int x) {
    	if(sgt[x].lzy) {
    		sgt[x << 1].lzy += sgt[x].lzy;
    		sgt[x << 1 | 1].lzy += sgt[x].lzy;
    		sgt[x << 1].dif += sgt[x].lzy;
    		sgt[x << 1 | 1].dif += sgt[x].lzy;
    		sgt[x].lzy = 0;
    		spreadd(x << 1);
    		spreadd(x << 1 | 1);
    		spreadd(x);
    	}
    }
    
    int search(int x, int l, int r) {
        if(l <= sgt[x].l && sgt[x].r <= r) {
            return sgt[x].val;
        }
    	spread(x);
    	int mid = (sgt[x].l + sgt[x].r) / 2;
    	if(mid < l) return search(x << 1 | 1, l, r);
    	if(mid >= r) return search(x << 1, l, r);
    	return search(x << 1, l, mid) + search(x << 1 | 1, mid + 1, r);
    }
    
    void change(int x, int l, int r)
    {
    	if(l == sgt[x].l && r == sgt[x].r)
    	{
    		sgt[x].lzy++;
    		sgt[x].dif++;
            spreadd(x);
    		return;
    	}
    	spread(x);
    	int mid = (sgt[x].l + sgt[x].r) / 2;
    	bool flag = 1;
    	if(mid < l) change(x << 1 | 1, l, r), flag=0;
    	if(mid >= r) change(x << 1, l, r), flag=0;
    	if(flag) {
    		change(x << 1, l, mid);
    		change(x << 1 | 1, mid + 1, r);
    	}
    	opt(x);
    }
    
    int main() {
    //	freopen(".in", "r", stdin);
    //	freopen(".out", "w", stdout);
        scanf("%d%d", &n, &m);
        char c = getchar();
    
        while(c < '0' || c > '9') c = getchar();
    
        for(int i = 1; i <= n; i++) {
            a[i] = c - '0';
            c = getchar();
        }
    
        build(1, 1, n);
    
        for(register int i = 1; i <= m; i++) {
    		int l, r;
    		scanf("%d%d", &l, &r);
    		printf("%d
    ", search(1, l, r));
    		change(1, l, r);
        }
    
        return 0;
    }
    
  • 相关阅读:
    运算符
    格式化输出
    while循环
    if 判断语句
    Swift # 字典
    Swift # 数组
    Swift # 字符串
    [ Swift # 函数 ]
    [ Bubble Sort ]& block
    数据结构 # 二叉树/堆/栈
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/12595874.html
Copyright © 2011-2022 走看看