zoukankan      html  css  js  c++  java
  • Rikka with Phi 线段树

    Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. 

    There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board: 

    1. "C A B C" Color the board from segment A to segment B with color C. 
    2. "P A B" Output the number of different colors painted between segment A and segment B (including). 

    In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your. 

    Input

    First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously.

    Output

    Ouput results of the output operation in order, each line contains a number.

    Sample Input

    2 2 4
    C 1 1 2
    P 1 2
    C 2 2 2
    P 1 2
    

    Sample Output

    2
    1

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int MAXN = 1e7 + 9;
    const int N = 3e5 + 10;
    LL euler[MAXN];
    void geteuler()
    {
        memset(euler, 0, sizeof(euler));
        euler[1] = 1;
        for (LL i = 2; i < MAXN; i++)
        {
            if (!euler[i])
                for (LL j = i; j < MAXN; j += i) 
                {
                    if (!euler[j]) euler[j] = j;
                    euler[j] = euler[j] / i * (i - 1);
                }
        }
    }
    struct node
    {
        int l, r;
        LL sum, laz;
    }T[N * 4 + 7];
    LL a[N];
    void pushup(int p)
    {
        T[p].sum = T[p * 2].sum + T[p * 2 + 1].sum;
        if (T[p * 2].laz == T[p * 2 + 1].laz)
            T[p].laz = T[p * 2].laz;
        else
            T[p].laz = 0;
    }
    void pushdown(int p)
    {
        if (T[p].laz)
        {
            T[p * 2].laz = T[p * 2 + 1].laz = T[p].laz;
            T[p * 2].sum = T[p].laz * (T[p * 2].r - T[p * 2].l + 1);
            T[p * 2 + 1].sum = T[p].laz * (T[p * 2 + 1].r - T[p * 2 + 1].l + 1);
        }
    }
    void update1(int x, int l, int r)
    {
        if (T[x].laz&&T[x].l == l&&T[x].r == r)
        {
            T[x].laz = euler[T[x].laz];
            T[x].sum = T[x].laz * (T[x].r - T[x].l + 1);
            return;
        }
        pushdown(x);
        int mid = (T[x].l + T[x].r) / 2;
        if (r <= mid)
            update1(x * 2, l, r);
        else if(l > mid)
            update1(x * 2 + 1, l , r);
        else
        {
            update1(x * 2, l, mid);
            update1(x * 2 + 1, mid + 1, r);
        }
        pushup(x);
    }
    void update2(int x, int l, int r, LL val)
    {
        if (l == T[x].l&&r == T[x].r)
        {
            T[x].laz = val;
            T[x].sum = (T[x].r - T[x].l + 1)*T[x].laz;
            return;
        }
        pushdown(x);
        int mid = (T[x].l + T[x].r) / 2;
        if (r <= mid)
            update2(x * 2, l, r, val);
        else if (l > mid)
            update2(x * 2 + 1, l, r, val);
        else
        {
            update2(x * 2, l, mid, val);
            update2(x * 2 + 1, mid + 1, r, val);
        }
        pushup(x);
    }
    
    void build(int x, int l, int r)
    {
        T[x].l = l, T[x].r = r;
        T[x].laz = T[x].sum = 0;
        if (l == r)
        {
            T[x].laz =  T[x].sum = a[l];
            return;
        }
        int mid = (l + r) / 2;
        build(x * 2, l, mid);
        build(x * 2 + 1, mid + 1, r);
        pushup(x);
    }
    
    LL query(int x, int l, int r)
    {
        if (T[x].l == l&&T[x].r == r)
            return T[x].sum;
        int mid = (T[x].l + T[x].r) / 2;
        pushdown(x);
        if (r <= mid)
            return query(x * 2, l, r);
        else if (l > mid)
            return query(x * 2 + 1, l, r);
        else
            return query(x * 2, l, mid) + query(x * 2 + 1, mid + 1, r);
    }
    int t, n, m;
    int main()
    {
        geteuler();
        ios::sync_with_stdio(0);
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++)
                scanf("%lld", &a[i]);
            build(1, 1, n);
            int op, L, R;
            LL tmp;
            while (m--)
            {
                scanf("%d%d%d", &op, &L, &R);
                if (op == 1)
                {
                    update1(1, L, R);
                }
                else if (op == 2)
                {
                    scanf("%lld", &tmp);
                    update2(1, L, R, tmp);
                }
                else if (op == 3)
                {
                    printf("%lld
    ", query(1, L, R)); 
                }
            }
        }
    }
    
    

    Count Color

     
    修改节点的值,查询区间总和
    这里laz就表示当前区间元素是否相同
    
    pushdown 顺推
    pushup
    只有当左右两边都是整块而且左右边的颜色相等才能设置laz = 1
    这里多了一个左右都是整块的条件是因为在欧拉的题目中laz>0就表示是整块了
    
    Rikka with Phi 
    laz有两个含义:laz==0 表示当前区间多个元素值不同
    laz == x 表示当前区间元素的值都是x
    修改节点的值,查询区间总和
    pushdown
    顺推即可,laz 相同, sum计算一下
    pushup
    当前sum = 子区间sum之和
    当前laz = 子区间laz 相同? 子区间laz,否则为0
    
    
    
    分为块状区域统一处理,当处理比当前块更小的块的时候,把之前积累的信息传递下去,递归处理
    
    两个题的区别在于颜色的题目不需要Laz来表示当前值,当前值用color表示即可
    
    PUSHDOWN 
    更新结点数据
    PUSHUP
    根据结点更新当前点的数据
  • 相关阅读:
    CentOS 6找不到partprobe命令的解决方法
    RTL源码归类与路径
    拓扑排序
    Char、AnsiChar、WideChar、PChar、PAnsiChar、PWideChar 的区别
    Delphi Byte与数据类型之间的转换
    Delphi byte[]转换为int
    Delphi Byte数组与Int String之间的相互转换
    delphi TTcpClient TTcpServer分析
    Delph7中TcpClient和TcpServer用法分析
    动态数组的使用
  • 原文地址:https://www.cnblogs.com/joeylee97/p/7403933.html
Copyright © 2011-2022 走看看