LightOJ 1135 - Count the Multiples of 3 线段树

Posted ( m Lweleth)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ 1135 - Count the Multiples of 3 线段树相关的知识,希望对你有一定的参考价值。

 

http://www.lightoj.com/volume_showproblem.php?problem=1135

题意:给定两个操作,一个对区间所有元素加1,一个询问区间能被3整除的数有多少个。

思路:要求被3整除,我们可以记录3个状态,当前区间模3余1的 余2的 余0的,那么对一个数增加的时候,直接交换不同余数下的个数就可以了。

/** @Date    : 2016-12-06-20.00
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version :
  */

#include<bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

struct yuu
{
    int l, r;
    int add;
    int m0, m1, m2;
}tt[N << 2];

void pushup(int p)
{
    tt[p].m0 = tt[p << 1].m0 + tt[p << 1 | 1].m0;
    tt[p].m1 = tt[p << 1].m1 + tt[p << 1 | 1].m1;
    tt[p].m2 = tt[p << 1].m2 + tt[p << 1 | 1].m2;
}

void pushdown(int p)
{
    if(tt[p].add != 0)
    {
        tt[p].add %= 3;
        ///
        tt[p << 1].add += tt[p].add;
        if(tt[p].add == 2)
        {
            swap(tt[p << 1].m0 , tt[p << 1].m1);
            swap(tt[p << 1].m0 , tt[p << 1].m2);
        }
        else if(tt[p].add == 1)
        {
            swap(tt[p << 1].m0 , tt[p << 1].m2);
            swap(tt[p << 1].m1 , tt[p << 1].m0);
        }
        ///
        tt[p << 1 | 1].add += tt[p].add;
        if(tt[p].add == 2)
        {
            swap(tt[p << 1 | 1].m0 , tt[p << 1 | 1].m1);
            swap(tt[p << 1 | 1].m0 , tt[p << 1 | 1].m2);
        }
        else if(tt[p].add == 1)
        {
            swap(tt[p << 1 | 1].m0 , tt[p << 1 | 1].m2);
            swap(tt[p << 1 | 1].m1 , tt[p << 1 | 1].m0);
        }
        tt[p].add = 0;
    }
}

void build(int l, int r, int p)
{
    tt[p].l = l;
    tt[p].r = r;
    tt[p].add = tt[p].m0 = tt[p].m2 = tt[p].m1 = 0;
    if(l == r)
    {
        tt[p].m0 = 1;
        return ;
    }
    int mid = (l + r) >> 1;
    build(l , mid, p << 1);
    build(mid + 1, r, p << 1 | 1);
    pushup(p);
}

void updata(int l, int r, int v, int p)
{
    if(l <= tt[p].l && r >= tt[p].r)
    {
        tt[p].add += v;
        swap(tt[p].m0 , tt[p].m2);
        swap(tt[p].m1 , tt[p].m0);
        return ;
    }
    pushdown(p);
    int mid = (tt[p].l + tt[p].r) >> 1;
    if(l <= mid)
        updata(l, r, v, p << 1);
    if(r > mid)
        updata(l, r, v, p << 1 | 1);
    pushup(p);
}

int query(int l, int r, int p)
{
    if(l <= tt[p].l && r >= tt[p].r)
    {
        return tt[p].m0;
    }
    pushdown(p);
    int mid = (tt[p].l + tt[p].r) >> 1;
    int ans = 0;
    if(l <= mid)
        ans += query(l, r, p << 1);
    if(r > mid)
        ans += query(l, r, p << 1 | 1);
    return ans;
}
int main()
{
    int T;
    int cnt = 0;
    cin >> T;
    while(T--)
    {
        int n, q;
        scanf("%d%d", &n, &q);
        build(1, n, 1);
        printf("Case %d:\n", ++cnt);
        while(q--)
        {
            int t, x, y;
            scanf("%d%d%d", &t ,&x ,&y);
            if(t)
                printf("%d\n", query(x+1, y+1, 1));
            else
                updata(x+1, y+1, 1, 1);
        }
    }
    return 0;
}

以上是关于LightOJ 1135 - Count the Multiples of 3 线段树的主要内容,如果未能解决你的问题,请参考以下文章

LightOJ - 1095 - Arrange the Numbers(错排)

LightOJ - 1173 - The Vindictive Coachf(DP)

LightOJ 1342 Aladdin and the Magical Sticks [想法题]

Lightoj 1025 - The Specials Menu

lightoj 1382 - The Queue(树形dp)

LightOJ 1341(Aladdin and the Flying Carpet )算术基本定理