Transformation HDU-4578(线段树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578
Transformation
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)
Total Submission(s): 10436 Accepted Submission(s): 2697

Problem Description
Yuanfang is puzzled with the question below:
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<—ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<—ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<—c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.

Input
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: “1 x y c” or “2 x y c” or “3 x y c”. Operation 4 is in this format: “4 x y p”. (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.

Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.

Sample Input

5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0

Sample Output

307
7489

在做这道题之前大家先去做一下洛谷上的一道相似的题,但是比这道题简单一点,附上题目链接:
https://www.luogu.org/problem/P2023。

这道题真的是神仙题,在培训期间做的,打排位赛的时候想在练习一下线段树,所以在kuangbin上找了这道题来做,然后心态崩了,当时没做出来,就继续打排位赛了,打完了之后有一天没看了,然后今天来补这道题,从早上一直WA到晚上,才AC,博主都快疯了,找到了一点bug就去交,然后就WA,知道最后才发现公式整错了。。。好了,发完了牢骚,现在讲一下这道题吧。
这是一道线段树的好题。
题意大意是:
对于一个长度为N的序列a支持以下操作:
1:令所有满足l<=i<=r的ai全部编程ai+c。
2:令所有满足l<=i<=r的ai全部变为ai*c。
3:令所有满足l<=i<=r的ai全部变为c。
4:查询所有满足l<=i<=r的ai的p次方的和,并输出。
对于这道题来说,P的取值为1<=p<=3,所以可以用三个值来记录所区间中数的p次方的值,然后如果是进行乘法,就乘以给出的数的相对应的次方,如果是加法就应用乘法分配律将一个数的变化装换为区间中的数的变换。
比如说:
如果我们更新加法之后的区间的值,那么对于一个结点的更新公式为:

平方:datep=(date+c)*(date+c)=date*date+2*date*c+c*c=datep+2*date*c+c*c.
立方:datel=(date+c)*(date+c)*(date+c)=date^3+3*date*c^2+3*date^2*c+c^3.

然后通过一个结点的更新推到区间的更新,通过乘法分配律,

datepq(区间总值)=(datep1+2*date1*c+c*c)+(datep2+2*date2*c+c*c)+(datep3+2*date3*c+c*c)+...+(datepr+2*dater*c+c*c)=datepq+2*dateq*c+len*c*c.

3次幂的时候也是一样的推理,然后我们就可以直接通过懒标记计算了(博主就是在这里WA了半天,枯了)。
然后就是处理优先级的问题了,加法和乘法的运算顺序,如果在乘法运算之前有加法,那么也需要把加法的懒标记也加入乘法的运算,这个也是乘法分配律的内容。如果遇到赋值的要求就将之前的标记全部初始化,因为有了赋值操作之后,之前的运算都算全部作废了,然后更新结点的值就Ok了,说了这么多,接下来就直接看代码吧。我觉得其实看代码更容易看懂吧。
代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=10007;
typedef long long ll;
const int maxn=1e5+7;
struct node
{
    ll l,r;
    ll lazyc,lazyj,date;
    ll lazyd;
    ll date1,date2;
}t[maxn<<2];

void build(ll root,ll l,ll r)
{
    t[root].l=l;
    t[root].r=r;
    t[root].date=0;
    t[root].date1=0;
    t[root].date2=0;
    t[root].lazyc=1;
    t[root].lazyd=0;
    t[root].lazyj=0;
    if(l==r)return ;
    ll mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
}

ll quite_mi(ll n,ll m);

void pushdown(ll root)
{
    if(t[root].lazyd){
        t[root<<1].date=(t[root<<1].r-t[root<<1].l+1)%mod*(t[root].lazyd%mod)%mod;
        t[root<<1|1].date=(t[root<<1|1].r-t[root<<1|1].l+1)%mod*(t[root].lazyd%mod)%mod;

        t[root<<1].date1=(t[root<<1].r-t[root<<1].l+1)%mod*(quite_mi(t[root].lazyd,2)%mod)%mod;
        t[root<<1|1].date1=(t[root<<1|1].r-t[root<<1|1].l+1)%mod*(quite_mi(t[root].lazyd,2)%mod)%mod;

        t[root<<1].date2=(t[root<<1].r-t[root<<1].l+1)%mod*(quite_mi(t[root].lazyd,3)%mod)%mod;
        t[root<<1|1].date2=(t[root<<1|1].r-t[root<<1|1].l+1)%mod*(quite_mi(t[root].lazyd,3)%mod)%mod;

        t[root<<1].lazyc=1;
        t[root<<1|1].lazyc=1;

        t[root<<1].lazyj=0;
        t[root<<1|1].lazyj=0;

        t[root<<1].lazyd=t[root].lazyd;
        t[root<<1|1].lazyd=t[root].lazyd;

        t[root].lazyd=0;
    }
    if(t[root].lazyc>1){
        t[root<<1].date=(t[root<<1].date%mod*(t[root].lazyc%mod))%mod;
        t[root<<1|1].date=(t[root<<1|1].date%mod*(t[root].lazyc%mod))%mod;

        //平方
        t[root<<1].date1=(t[root<<1].date1*(quite_mi(t[root].lazyc,2)%mod))%mod;
        t[root<<1|1].date1=(t[root<<1|1].date1*(quite_mi(t[root].lazyc,2)%mod))%mod;

        //立方
        t[root<<1].date2=(t[root<<1].date2*(quite_mi(t[root].lazyc,3)%mod))%mod;
        t[root<<1|1].date2=(t[root<<1|1].date2*(quite_mi(t[root].lazyc,3)%mod))%mod;

        //状态转移
        t[root<<1].lazyc=(t[root<<1].lazyc%mod*(t[root].lazyc%mod))%mod;
        t[root<<1|1].lazyc=(t[root<<1|1].lazyc%mod*(t[root].lazyc%mod))%mod;

        t[root<<1].lazyj=(t[root<<1].lazyj%mod*(t[root].lazyc%mod))%mod;
        t[root<<1|1].lazyj=(t[root<<1|1].lazyj%mod*(t[root].lazyc%mod))%mod;

        t[root].lazyc=1;
    }
    if(t[root].lazyj){
        int lenl=t[root<<1].r-t[root<<1].l+1;
        int lenr=t[root<<1|1].r-t[root<<1|1].l+1;
        lenl%=mod;
        lenr%=mod;

        //立方和公式第一步
        t[root<<1].date2=(t[root<<1].date2+3*(t[root].lazyj%mod)%mod*(t[root<<1].date1%mod))%mod;
        t[root<<1|1].date2=(t[root<<1|1].date2+3*(t[root].lazyj%mod)%mod*(t[root<<1|1].date1%mod))%mod;

        //立方和公式第二步
        t[root<<1].date2=(t[root<<1].date2+3*(t[root<<1].date)%mod*(quite_mi(t[root].lazyj,2)%mod))%mod;
        t[root<<1|1].date2=(t[root<<1|1].date2+3*(t[root<<1|1].date)%mod*(quite_mi(t[root].lazyj,2)%mod))%mod;

        //立方和第三步
        t[root<<1].date2=(t[root<<1].date2+lenl*quite_mi(t[root].lazyj,3)%mod)%mod;
        t[root<<1|1].date2=(t[root<<1|1].date2+lenr*quite_mi(t[root].lazyj,3)%mod)%mod;

        //平方和公式
        t[root<<1].date1=(t[root<<1].date1+2*t[root<<1].date%mod*(t[root].lazyj%mod)%mod)%mod;
        t[root<<1|1].date1=(t[root<<1|1].date1+2*t[root<<1|1].date%mod*(t[root].lazyj%mod)%mod)%mod;

        //平方和公式第二步
        t[root<<1].date1=(t[root<<1].date1+lenl*quite_mi(t[root].lazyj,2)%mod)%mod;
        t[root<<1|1].date1=(t[root<<1|1].date1+lenr*quite_mi(t[root].lazyj,2)%mod)%mod;

        //一次
        t[root<<1].date=(t[root<<1].date%mod+lenl*t[root].lazyj%mod)%mod;
        t[root<<1|1].date=(t[root<<1|1].date%mod+lenr*t[root].lazyj%mod)%mod;

        t[root<<1].lazyj=(t[root<<1].lazyj%mod+(t[root].lazyj%mod))%mod;
        t[root<<1|1].lazyj=(t[root<<1|1].lazyj%mod+(t[root].lazyj%mod))%mod;

        t[root].lazyj=0;
    }
}

void change(ll root,ll l,ll r,ll c,int flag)
{
    if(l<=t[root].l && r>=t[root].r){
        if(flag==3){
            t[root].date=(t[root].r-t[root].l+1)%mod*(c%mod)%mod;
            t[root].date1=(t[root].r-t[root].l+1)%mod*quite_mi(c,2)%mod;
            t[root].date2=(t[root].r-t[root].l+1)%mod*quite_mi(c,3)%mod;
            t[root].date%=mod;
            t[root].date1%=mod;
            t[root].date2%=mod;
            t[root].lazyd=c;
            t[root].lazyc=1;
            t[root].lazyj=0;
            return ;
        }
        int len=t[root].r-t[root].l+1;
        len%=mod;
        if(flag==2){
            t[root].date=(t[root].date%mod*(c%mod))%mod;

            //平方
            t[root].date1=(t[root].date1%mod*(quite_mi(c,2)%mod))%mod;

            //立方
            t[root].date2=(t[root].date2%mod*(quite_mi(c,3)%mod))%mod;

            t[root].lazyc=(t[root].lazyc%mod*(c%mod))%mod;
            t[root].lazyj=(t[root].lazyj%mod*(c%mod))%mod;
            return ;
        }
        if(flag==1){//加法
            //立方
            t[root].date2=(t[root].date2+3*(c%mod)%mod*(t[root].date1%mod)%mod+3*(t[root].date%mod)*(quite_mi(c%mod,2)%mod)%mod+len*quite_mi(c,3)%mod)%mod;

            //平方
            t[root].date1=(t[root].date1+2*(c%mod)%mod*t[root].date%mod+len*quite_mi(c%mod,2)%mod)%mod;

            t[root].date=(t[root].date+(t[root].r-t[root].l+1)%mod*(c%mod))%mod;
            t[root].lazyj=(t[root].lazyj+c%mod)%mod;
            return ;
        }
    }
    pushdown(root);
    ll mid=(t[root].l+t[root].r)>>1;
    if(l<=mid){
        change(root<<1,l,r,c,flag);
    }
    if(r>mid){
        change(root<<1|1,l,r,c,flag);
    }
    t[root].date=(t[root<<1].date+t[root<<1|1].date)%mod;
    t[root].date1=(t[root<<1].date1+t[root<<1|1].date1)%mod;
    t[root].date2=(t[root<<1].date2+t[root<<1|1].date2)%mod;
}

ll quite_mi(ll n,ll m)
{
    ll ans=1;
    while(m){
        if(m&1) ans=(ans%mod*(n%mod))%mod;
        n=((n%mod)*(n%mod))%mod;
        m>>=1;
    }
    return ans;
}

ll query(ll root,ll l,ll r,ll p)
{
    if(r<t[root].l || t[root].r<l)return 0;
    if(l<=t[root].l && r>=t[root].r){
        if(p==1){
            return t[root].date%mod;
        }
        else if(p==2){
            return t[root].date1%mod;
        }
        else{
            return t[root].date2%mod;
        }
    }
    ll mid=(t[root].l+t[root].r)>>1;
    pushdown(root);
    ll ans=0;
    if(l<=mid){
        ans=(ans+query(root<<1,l,r,p))%mod;
    }
    if(r>mid){
        ans=(ans+query(root<<1|1,l,r,p))%mod;
    }
    return ans;
}

int main()
{
    ll n,m;
    while(~scanf("%lld%lld",&n,&m)){
        if(n==0 || m==0){
            return 0;
        }
        build(1,1,n);
        while(m--){
            int flag;
            ll l,r,p;
            scanf("%d%lld%lld%lld",&flag,&l,&r,&p);
            if(flag==4){
                printf("%lld\n",query(1,l,r,p)%mod);
            }
            else{
                //p%=mod;
                change(1,l,r,p,flag);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值