2022 ICPC Gran Premio de Mexico 2da Fecha Final standings - K. Krystalova‘s Trivial Problem

本文介绍了一种使用线段树解决区间加法与区间平方和查询问题的方法。通过维护原元素值与平方和值,实现高效更新与查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

K. Krystalova’s Trivial Problem

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output

题目描述

Krystalova is writing trivial problems (as always) but now for some reason (lucky for you) she also wrote a trivial statement.

You have a trivial list of numbers L, and two trivial operations:

  1. u l r x: Add x to the numbers in L in the range [l,r].

  2. q l r: Get the sum of L2i for every i in the range [l,r].

输入描述

In the first line of input two integers N (1≤N≤10^5), Q (1≤Q≤10^4), the size of L and the number of operations respectively.

The next line contains N integers Li (0≤Li≤10^8), the elements of L.

The next Q lines contains an operation, that can be one of the two types described before. If the line starts with a letter “u” then will be three integers l (1≤l≤N), r (1≤r≤N), x (−108≤x≤108). If the line starts with a letter “q” then will be two integers l (1≤l≤N), r (1≤r≤N)

输出描述

For every operation of type 2, print in one line the result of the operation. As the answer might be very large, please output the answer modulo 10^9+7

输入样例1:

5 5
1 1 1 1 1
u 1 3 1
q 1 5
u 3 5 1
q 3 3
q 1 5

输出样例1:

14
9
25

题意

给定一个长度为 n 的数组 q 次 询问
i) 选择 一段区间加上 x
ii) 输出一段区间的元素平方和

思路

一眼数据结构 线段树魔改下
定义原元素为 y 平方为 y^2
加上 x 后原元素变为了 y+x 平方为 y 2 + 2 x y + x 2 y^2+2xy+x^2 y2+2xy+x2
对比可知即原元素 乘上 2x 再加上 x^2
平方和 更新为 y 2 ( 原平分和 ) + 2 x y + x 2 y^2(原平分和)+2xy+x^2 y2(原平分和)+2xy+x2
我们只需要在线段树数组里保存原元素的值用以更新平分和的值即可
故更新时应先更新平方和的值再更新原元素的值

取模细节多注意下 容易爆long long

Code

#include<bits/stdc++.h>
using namespace std;

int p;
struct segtree
{
    long long v,vv,mul,add;
}st[400003];
long long a[100003];
void pushup(int rt)
{
    st[rt].v=(st[rt<<1].v+st[rt<<1|1].v)%p;
    st[rt].vv=(st[rt<<1].vv+st[rt<<1|1].vv)%p;
}
void build(int l,int r,int rt)
{
    st[rt].mul=1;
    st[rt].add=0;
    if(l==r)
    {
        st[rt].v=a[l];
        st[rt].vv=(a[l]*a[l])%p;
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void pushdown(int ln,int rn,int rt)
{
    st[rt<<1].vv=((st[rt<<1].vv+2*st[rt].add*st[rt<<1].v%p+st[rt].add*st[rt].add%p*ln%p)%p+p)%p;
    st[rt<<1|1].vv=((st[rt<<1|1].vv+2*st[rt].add*st[rt<<1|1].v%p+st[rt].add*st[rt].add%p*rn)%p+p)%p;
    st[rt<<1].v=(st[rt<<1].v*st[rt].mul+st[rt].add*ln)%p;
    st[rt<<1|1].v=(st[rt<<1|1].v*st[rt].mul+st[rt].add*rn)%p;
    st[rt<<1].mul=(st[rt<<1].mul*st[rt].mul)%p;
    st[rt<<1|1].mul=(st[rt<<1|1].mul*st[rt].mul)%p;
    st[rt<<1].add=(st[rt<<1].add*st[rt].mul+st[rt].add)%p;
    st[rt<<1|1].add=(st[rt<<1|1].add*st[rt].mul+st[rt].add)%p;
    st[rt].mul=1;
    st[rt].add=0;
}
long long ask(int al,int ar,int l,int r,int rt)
{
    if(l>=al&&r<=ar)return st[rt].vv%p;
    if(r<al||l>ar)return 0;
    int m=(l+r)>>1;
    pushdown(m-l+1,r-m,rt);
    return (ask(al,ar,l,m,rt<<1)%p+ask(al,ar,m+1,r,rt<<1|1))%p;
}
void addupdate(int ul,int ur,long long d,int l,int r,int rt)
{
    if(l>=ul&&r<=ur)
    {
        st[rt].vv=(((st[rt].vv+(2*d*st[rt].v)%p)%p+d*d%p*(r-l+1)%p)%p+p)%p;
        st[rt].v=(st[rt].v+d*(r-l+1))%p;//v不能先更新,v^2更新依赖旧的v
        st[rt].add=(st[rt].add+d)%p;
        return;
    }
    int m=(l+r)>>1;
    pushdown(m-l+1,r-m,rt);
    if(m>=ul)addupdate(ul,ur,d,l,m,rt<<1);
    if(ur>m)addupdate(ul,ur,d,m+1,r,rt<<1|1);
    pushup(rt);
}
inline void sol()
{
    int n,q;
    scanf("%d%d",&n,&q);
    p=1e9+7;
    for(int i=1;i<=n;++i)
    {
        scanf("%lld",&a[i]);
    }
    build(1,n,1);
    char cz;
    int l,r;
    long long x;
    while(q--)
    {
        scanf(" %c%d%d",&cz,&l,&r);
        if(cz=='u')
        {
            scanf("%lld",&x);
            addupdate(l,r,x,1,n,1);
        }
        else
        {
            printf("%lld\n",ask(l,r,1,n,1));
        }
    }
}
int main()
{
    sol();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯西可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值