zoukankan      html  css  js  c++  java
  • HDU 5828 Rikka with Sequence (线段树)

    Rikka with Sequence

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5828

    Description

    As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them: Yuta has an array A with n numbers. Then he makes m operations on it. There are three type of operations: 1 l r x : For each i in [l,r], change A[i] to A[i]+x 2 l r : For each i in [l,r], change A[i] to 3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r] It is too difficult for Rikka. Can you help her?

    Input

    The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000. For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation. It is guaranteed that 1<=A[i],x<=100000.

    Output

    For each operation of type 3, print a lines contains one number -- the answer of the query.

    Sample Input

    1 5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5

    Sample Output

    5 6

    Source

    2016 Multi-University Training Contest 8
    ##题意: 对一个数组进行若干操作: 1. 将区间内的值都加x. 2. 将区间内的值都开平方. 3. 求区间内数的和.
    ##题解: 容易想到用线段树来维护,关键是如何处理操作二. 直接对每个数开平方肯定会超时. 考虑到开平方操作的衰减速度很快,一个数最多经过6次开平方操作就会到1. 那么随着操作的进行,区间内的数会趋于相同,恰好利用这个点来作剪枝. 对于树中的每个结点维护一个equal, 表示当前结点的子节点是否相等. (若相等就等于子节点的值,否则为-1). 当更新到某区间时,若区间内的值都相同,则只更新到这里即可,下面的结点利用pushdown来更新.
    赛后数据被加强了,上述思路在HDU上已经AC不了了. sad....

    ##代码: ``` cpp #include #include #include #include #include #include #include #include #include #include #include #define LL long long #define eps 1e-8 #define maxn 101000 #define mod 100000007 #define inf 0x3f3f3f3f #define mid(a,b) ((a+b)>>1) #define IN freopen("in.txt","r",stdin); using namespace std;

    int n;
    LL num[maxn];
    struct Tree
    {
    int left,right;
    LL lazy,sum,equl;
    }tree[maxn<<2];

    void build(int i,int left,int right)
    {
    tree[i].left=left;
    tree[i].right=right;
    tree[i].lazy=0;

    if(left==right){
        tree[i].sum = num[left];
        tree[i].equl = num[left];
        return ;
    }
    
    int mid=mid(left,right);
    
    build(i<<1,left,mid);
    build(i<<1|1,mid+1,right);
    
    tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
    tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;
    

    }

    void pushdown(int i)
    {
    if(tree[i].equl != -1) {
    tree[i<<1].equl = tree[i].equl;
    tree[i<<1|1].equl = tree[i].equl;
    tree[i<<1].sum = (tree[i<<1].right-tree[i<<1].left+1)tree[i].equl;
    tree[i<<1|1].sum = (tree[i<<1|1].right-tree[i<<1|1].left+1)
    tree[i].equl;
    tree[i].lazy = 0;
    tree[i<<1].lazy = 0;
    tree[i<<1|1].lazy = 0;
    }
    if(tree[i].lazy) {
    tree[i<<1].lazy += tree[i].lazy;
    tree[i<<1|1].lazy += tree[i].lazy;
    tree[i<<1].sum += (tree[i<<1].right-tree[i<<1].left+1)tree[i].lazy;
    tree[i<<1|1].sum += (tree[i<<1|1].right-tree[i<<1|1].left+1)
    tree[i].lazy;
    if(tree[i<<1].equl != -1) {
    tree[i<<1].equl += tree[i].lazy;
    tree[i<<1].lazy = 0;
    }
    if(tree[i<<1|1].equl != -1) {
    tree[i<<1|1].equl += tree[i].lazy;
    tree[i<<1|1].lazy = 0;
    }
    tree[i].lazy = 0;
    }
    }

    void update(int i,int left,int right,LL d)
    {
    if(tree[i].leftleft&&tree[i].rightright)
    {
    tree[i].sum += (right-left+1)*d;
    if(tree[i].equl == -1) tree[i].lazy += d;
    else tree[i].equl += d;
    return ;
    }

    pushdown(i);
    
    int mid=mid(tree[i].left,tree[i].right);
    
    if(right<=mid) update(i<<1,left,right,d);
    else if(left>mid) update(i<<1|1,left,right,d);
    else {
        update(i<<1,left,mid,d);
        update(i<<1|1,mid+1,right,d);
    }
    
    tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
    tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;
    

    }

    void update_sqrt(int i,int left,int right)
    {
    if(tree[i].leftleft&&tree[i].rightright && tree[i].equl!=-1)
    {
    tree[i].equl = (LL)sqrt(tree[i].equl);
    tree[i].sum = tree[i].equl * (tree[i].right-tree[i].left+1);
    tree[i].lazy = 0;
    return ;
    }

    pushdown(i);
    
    int mid=mid(tree[i].left,tree[i].right);
    
    if(right<=mid) update_sqrt(i<<1,left,right);
    else if(left>mid) update_sqrt(i<<1|1,left,right);
    else {
        update_sqrt(i<<1,left,mid);
        update_sqrt(i<<1|1,mid+1,right);
    }
    
    tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
    tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;
    

    }

    LL query(int i,int left,int right)
    {
    if(tree[i].leftleft&&tree[i].rightright)
    return tree[i].sum;

    pushdown(i);
    
    int mid=mid(tree[i].left,tree[i].right);
    
    if(right<=mid) return query(i<<1,left,right);
    else if(left>mid) return query(i<<1|1,left,right);
    else return query(i<<1,left,mid)+query(i<<1|1,mid+1,right);
    

    }

    int main(int argc, char const *argv[])
    {
    //IN;

    int t; cin >> t;
    while(t--)
    {
        int m;
        scanf("%d %d", &n,&m);
        for(int i=1; i<=n; i++)
            scanf("%lld", &num[i]);
        build(1, 1, n);
    
        while(m--) {
            int op, l, r;
            scanf("%d %d %d", &op,&l,&r);
            if(op == 1) {
                LL x; scanf("%lld", &x);
                update(1, l, r, x);
            }
            else if(op == 2) {
                update_sqrt(1, l, r);
            }
            else if(op == 3) {
                printf("%lld
    ", query(1, l, r));
            }
        }
    }
    
    return 0;
    

    }

  • 相关阅读:
    【转载】sourcetree 克隆项目显示“这是一个无效的源路径”
    【转载】SQL 查询某个数据是否存在
    【转载】windows 静默安装 winpcap
    Linux expect 远程自动登录机器并执行命令
    CentOS 静态编译缺少库文件 /usr/lib/ld: cannot find lxx
    Java常用工具类(随着工作持续更新)
    一些网址笔记
    1 msql的安装和配置
    postgresql 安装和配置
    有管django使用orm 字段报错问题
  • 原文地址:https://www.cnblogs.com/Sunshine-tcf/p/5766527.html
Copyright © 2011-2022 走看看