zoukankan      html  css  js  c++  java
  • HDU 4578 Transformation --线段树,好题

    题意: 给一个序列,初始全为0,然后有4种操作:

    1. 给区间[L,R]所有值+c

    2.给区间[L,R]所有值乘c

    3.设置区间[L,R]所有值为c

    4.查询[L,R]的p次方和(1<=p<=3)

    解法: 线段树,维护三个标记,addmark,mulmark,setmark分别表示3种更新,然后p[1],p[2],p[3]分别表示该节点的1,2,3次方和。标记传递顺序setmark一定是第一个,因为setmark可以使mulmark,addmark都失效还原,mulmark和addmark的顺序倒是无所谓。

    这题写了半个比赛时间,写的很迷,还是没写出来, 后来看了别人写的,才知道自己很多地方都没更新好甚至没更新。这题算是一道线段树的综合题了,混合了几种常见的更新,对线段树的整体把握很有帮助。

    比如:

    1.如果setmark有值,那么addmark,mulmark全部要还原。

    2.如果mulmark有值,那么addmark也要更新,更新为addmark*mulmark

    就是这两点一直没考虑到,WA了好久。

    在addmark下传过程中更新p[1],p[2],p[3]的方法如下:

    比如 a^3 -> (a+c)^3 的过程:  (a+c)^3 = a^3 + c^3 + 3a*c^2 + 3*a^2*c, a是变量, 所以提取出c,那么p[3]可以由p[1],p[2]推出,p[2]可以由p[1]推出。

    即 p[3] = p[3] + c^3 + 3*c^2*p[1] + 3*c*p[2] . 

    p[2]同理可以由p[1]推出。

    然后每次都做一下pushdown,就可以得出正确答案。

    当时像优化一下,少做几次pushdown,即这次的操作类型与上次一样就不pushdown,结果那样就会出现问题,还不如每次都pushdown呢。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #define Mod 10007
    #define SMod 10007
    using namespace std;
    #define N 100017
    
    struct node{
        int p[4];
        int setmark,addmark,mulmark;
    }tree[4*N];
    
    void pushup(int rt){
        for(int i=1;i<=3;i++) tree[rt].p[i] = (tree[2*rt].p[i] + tree[2*rt+1].p[i])%SMod;
    }
    
    void pushdown(int l,int r,int rt)
    {
        int mid = (l+r)/2;
        if(tree[rt].setmark)
        {
            int mk = tree[rt].setmark;
            tree[rt<<1].setmark = tree[rt<<1|1].setmark = mk;
            tree[rt<<1].addmark = tree[rt<<1|1].addmark = 0;
            tree[rt<<1].mulmark = tree[rt<<1|1].mulmark = 1;
    
            tree[rt<<1].p[1] = (mid-l+1)%Mod*mk%SMod;
            tree[rt<<1|1].p[1] = (r-mid)%Mod*mk%SMod;
    
            tree[rt<<1].p[2] = (mid-l+1)%Mod*mk%SMod*mk%SMod;
            tree[rt<<1|1].p[2] = (r-mid)%Mod*mk%SMod*mk%SMod;
    
            tree[rt<<1].p[3] = (mid-l+1)%Mod*mk%SMod*mk%SMod*mk%SMod;
            tree[rt<<1|1].p[3] = (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod;
            tree[rt].setmark = 0;
        }
        if(tree[rt].mulmark != 1)
        {
            int mk = tree[rt].mulmark;
            tree[rt<<1].mulmark *= mk, tree[rt<<1].mulmark%=SMod;
            tree[rt<<1|1].mulmark *= mk, tree[rt<<1|1].mulmark%=SMod;
    
            tree[rt<<1].addmark = tree[rt<<1].addmark%SMod*mk%SMod;
            tree[rt<<1|1].addmark = tree[rt<<1|1].addmark%SMod*mk%SMod;
    
            tree[rt<<1].p[1] = tree[rt<<1].p[1]%Mod*mk%SMod;
            tree[rt<<1|1].p[1] = tree[rt<<1|1].p[1]%Mod*mk%SMod;
    
            tree[rt<<1].p[2] = tree[rt<<1].p[2]%Mod*mk%SMod*mk%SMod;
            tree[rt<<1|1].p[2] = tree[rt<<1|1].p[2]%Mod*mk%SMod*mk%SMod;
    
            tree[rt<<1].p[3] = tree[rt<<1].p[3]%Mod*mk%SMod*mk%SMod*mk%SMod;
            tree[rt<<1|1].p[3] = tree[rt<<1|1].p[3]%Mod*mk%SMod*mk%SMod*mk%SMod;
            tree[rt].mulmark = 1;
        }
        if(tree[rt].addmark)
        {
            int mk = tree[rt].addmark;
            tree[rt<<1].addmark += mk, tree[rt<<1].addmark%SMod;
            tree[rt<<1|1].addmark += mk, tree[rt<<1|1].addmark%SMod;
    
            tree[rt<<1].p[3] = (tree[rt<<1].p[3]%Mod + (mid-l+1)%Mod*mk%SMod*mk%SMod*mk%SMod + 3*mk%Mod*tree[rt<<1].p[2]%SMod + 3*mk%SMod*mk%SMod*tree[rt<<1].p[1]%SMod)%SMod;
            tree[rt<<1|1].p[3] = (tree[rt<<1|1].p[3]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod + 3*mk%Mod*tree[rt<<1|1].p[2]%SMod + 3*mk%SMod*mk%SMod*tree[rt<<1|1].p[1]%SMod)%SMod;
    
            tree[rt<<1].p[2] = (tree[rt<<1].p[2]%Mod + (mid-l+1)%Mod*mk%SMod*mk%SMod + 2*mk%Mod*tree[rt<<1].p[1]%SMod)%SMod;
            tree[rt<<1|1].p[2] = (tree[rt<<1|1].p[2]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod + 2*mk%Mod*tree[rt<<1|1].p[1]%SMod)%SMod;
    
            tree[rt<<1].p[1] = (tree[rt<<1].p[1]%Mod + (mid-l+1)%Mod*mk%SMod)%SMod;
            tree[rt<<1|1].p[1] = (tree[rt<<1|1].p[1]%Mod + (r-mid)%Mod*mk%SMod)%SMod;
            tree[rt].addmark = 0;
        }
    }
    
    void build(int l,int r,int rt)
    {
        tree[rt].setmark = tree[rt].addmark = 0;
        tree[rt].mulmark = 1;
        memset(tree[rt].p,0,sizeof(tree[rt].p));
        if(l == r) return;
        int mid = (l+r)/2;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    }
    
    void update(int l,int r,int aa,int bb,int tag,int val,int rt)  //tag = 3 : set  2:mul 1: add
    {
        if(aa <= l && bb >= r)
        {
            if(tag == 3)
            {
                tree[rt].p[1] = (r-l+1)%Mod*val%SMod;
                tree[rt].p[2] = (r-l+1)%Mod*val%SMod*val%SMod;
                tree[rt].p[3] = (r-l+1)%Mod*val%SMod*val%SMod*val%SMod;
                tree[rt].setmark = val;
                tree[rt].addmark = 0;
                tree[rt].mulmark = 1;
            }
            else if(tag == 2)
            {
                tree[rt].p[1] = tree[rt].p[1]%SMod*val%SMod;
                tree[rt].p[2] = tree[rt].p[2]%SMod*val%SMod*val%SMod;
                tree[rt].p[3] = tree[rt].p[3]%SMod*val%SMod*val%SMod*val%SMod;
                tree[rt].mulmark = tree[rt].mulmark%SMod*val%SMod;
                tree[rt].addmark = tree[rt].addmark%SMod*val%SMod;
            }
            else if(tag == 1)
            {
                tree[rt].p[3] = (tree[rt].p[3]%SMod + (r-l+1)%SMod*val%SMod*val%SMod*val%SMod + 3*val%SMod*tree[rt].p[2]%SMod + 3*val%SMod*val%SMod*tree[rt].p[1]%SMod)%SMod;
                tree[rt].p[2] = (tree[rt].p[2]%SMod + (r-l+1)%SMod*val%SMod*val%SMod + 2*val%SMod*tree[rt].p[1]%SMod)%SMod;
                tree[rt].p[1] = (tree[rt].p[1]%SMod + (r-l+1)%SMod*val%SMod)%SMod;
                tree[rt].addmark = (tree[rt].addmark+val)%SMod;
            }
            return;
        }
        int mid = (l+r)/2;
        pushdown(l,r,rt);
        if(aa <= mid) update(l,mid,aa,bb,tag,val,rt<<1);
        if(bb > mid)  update(mid+1,r,aa,bb,tag,val,rt<<1|1);
        pushup(rt);
    }
    
    int query(int l,int r,int aa,int bb,int i,int rt)
    {
        if(aa > r || bb < l) return 0;
        if(aa <= l && bb >= r)
            return tree[rt].p[i];
        pushdown(l,r,rt);
        int res = 0;
        int mid = (l+r)/2;
        return (query(l,mid,aa,bb,i,rt<<1)%SMod+query(mid+1,r,aa,bb,i,rt<<1|1)%SMod)%SMod;
    }
    
    int main()
    {
        int n,m,i,j,op,x,y,c;
        while(scanf("%d%d",&n,&m)!=EOF && n+m)
        {
            build(1,n,1);
            while(m--)
            {
                scanf("%d%d%d%d",&op,&x,&y,&c);
                if(op != 4) update(1,n,x,y,op,c,1);
                else        printf("%d
    ",query(1,n,x,y,c,1)%SMod);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    barabasilab-networkScience学习笔记2-图理论
    barabasilab-networkScience学习笔记1-网络科学简介
    windows下R语言在终端的运行
    远程打印服务器
    矩震级Mw与地震矩M0的换算关系
    关于地震科学台阵数据中心的仪器记录值介绍
    capjoint中的tel3核心代码teleseis3.f90
    Centos7安装
    matlab中hold on 和hold off功能的区别
    sac cut
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4111701.html
Copyright © 2011-2022 走看看