序列--(树状数组维护等差数列模板)

简介: 题目描述eobiyye给了你一个长度为n的序列ai,序列中每个元素的初始值为0。接下来她会对这个序列进行m次操作,每次操作有4个参数l,r,s,e,表示将区间[l,r]加上一个首项为s,末项为e的等差数列。若一次操作中l=1,r=5,s=2,e=10,则对序列中第1~5个数分别加上2,4,6,8,10。现在Geobiyye要求你求出m次操作后序列中的每个数的值。

题目描述


eobiyye给了你一个长度为n的序列ai,序列中每个元素的初始值为0。

接下来她会对这个序列进行m次操作,每次操作有4个参数l,r,s,e,表示将区间[l,r]加上一个首项为s,末项为e的 等差数列

若一次操作中l=1,r=5,s=2,e=10,则对序列中第1~5个数分别加上2,4,6,8,10。

现在Geobiyye要求你求出m次操作后序列中的每个数的值。


输入


第一行2个整数n,m,表示序列长度和操作数。

接下来m行,每行4个整数l,r,s,e,含义见题目描述。

数据保证等差数列中的每一项都是整数。


输出


由于输出数据过大,Geobiyye只想要知道最终序列每一项的异或和,即。(其中表示二进制下的异或操作,在c++中为^)


样例输入 Copy


5 2
1 5 2 10
2 4 1 1


样例输出


3


提示


样例解释:


第一次操作加的数列:2 4 6 8 10

第二次操作加的数列:0 1 1 1 0

所有操作结束后序列每个元素值为:2 5 7 9 10。

输出异或和,就是3。


【数据范围】


对于30%的数据:n,m≤1000 。

对于50%的数据:n,m≤100000。

对于另外20%的数据:s=e。

对于100%的数据:n,m≤500000,1≤l<r≤n。

数据保证输入数据以及在任何时候序列中的数在[0,9×1018]范围内。


本题输入文件较大,Geobiyye给了你一份快速读入的模板。

template <typename T> void read(T &x){
int f=1;x=0;char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
for (; isdigit(c);c=getchar()) x=x*10+c-'0';
x*=f;
}

你可以使用函数read(x)读入一个int或long long类型的整数。

以下为示范程序:

#include<bits/stdc++.h>
using namespace std;
template <typename T> void read(T &x){
  int f=1;x=0;char c=getchar();
  for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
  for (; isdigit(c);c=getchar()) x=x*10+c-'0';
  x*=f;
}
int n;
long long m;
int main(){
  read(n);//读入int类型变量n
  read(m);//读入long long类型变量m
  return 0;
}

这道题通过线段树和 树状数组 都可以完成,但是线段树比较复杂,代码也比较多~~(我懒)~~ ,然后写了写树状数组

这道题是洛谷上的一道类似的题,可以先了解一下洛谷上的 这道题 ,然后两道题有异曲同工之妙,可以了解下

如果将洛谷上的题和这个题类比的话,先要进行预处理等差数列的首项,公差

a1=a1

a2=a1+d

a3=a1+2d

an=a1+(n-1)d

公差=>d== (an-a1)/(n-1)

==(ar-al) / (r-l)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
  ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
    if(c == '-')Nig = -1,c = getchar();
    while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
    return Nig*x;}
#define read read()
const ll inf = 1e15;
const ll INF = 0x3f3f3f3f;
const int maxn = 5e5 + 7;
const int mod = 1e9+9;
typedef int itn;
#define pi 3.14159265358979323846
ll n,m;
ll a[maxn];
ll tree[maxn][2];
ll _low_b(ll x){ return x&(-x); }
void _add(int pos,ll s,ll e){
    ///       位置 首相  公差
    for(int i=pos;i<=n;i+=_low_b((ll)i)){
        tree[i][0]+=s;tree[i][1]+=e;
        s+=e*(_low_b((ll)i));
    }
}
ll _GetSum(int pos){
    ll sum=0;
    int tx=pos;
    while(tx){
        sum+=tree[tx][0]+tree[tx][1]*(pos-tx);
        tx-=_low_b((ll)tx);
    }return sum;
}
int main()
{
    n=read,m=read;
    for(int i=1;i<=m;i++){
        int left=read,right=read;
        ll shou=read,mo=read;
        ll cha=mo-shou;
        cha/=(right-left);
        _add(left,shou,cha);
        _add(right+1,-1*(right+1-left)*cha-shou,-cha);
    }
    ll res=0;
    for(int i=1;i<=n;i++){ res^=_GetSum(i); }
    cout<<res<<endl;
    return 0;
}
/**
5 2
1 5 2 10
2 4 1 1
**/



目录
相关文章
|
8月前
|
算法 测试技术 C++
【动态规划】【前缀和】【数学】2338. 统计理想数组的数目
【动态规划】【前缀和】【数学】2338. 统计理想数组的数目
|
8月前
|
算法 测试技术 C#
二分查找:LeetCode2035:将数组分成两个数组并最小化数组和的差
二分查找:LeetCode2035:将数组分成两个数组并最小化数组和的差
|
8月前
|
C语言
c语言编程练习题:7-51 求奇数分之一序列前N项和
c语言编程练习题:7-51 求奇数分之一序列前N项和
79 0
|
8月前
|
算法
DAY-7 | 牛客-BM21 寻找旋转数组的最小元素:二分法分治思想真的很可靠
这是一个关于编程题目的摘要:题目是牛客网上的&quot;BM21 旋转数组的最小数字&quot;,要求找到旋转数组中的最小数字。题解介绍了使用二分查找算法来解决此问题,因为其时间复杂度优于暴力搜索的线性时间复杂度。二分查找的核心是通过比较中间元素与右端元素的大小,不断缩小搜索范围,最终找到最小值。代码示例展示了如何实现这个算法。总结中强调了二分查找适用于部分有序数组,并指出了解决这类问题的关键在于理解数组的二段单调性。
50 1
|
7月前
|
移动开发 C++
【洛谷 P1157】组合的输出 题解(深度优先搜索+枚举子集)
该问题要求编程输出从1到n中选择r个元素的所有组合,组合按字典序排列。输入包含两自然数n和r(1&lt;n&lt;21, 0≤r≤n)。输出每个组合时,每个数字占据3个字符宽度。提供的AC代码使用C++,通过递归搜索方法枚举子集。样例输入为5 3,输出显示所有3个元素的组合。
59 0
|
8月前
【错题集-编程题】删除相邻数字的最大分数(动态规划 - 线性 dp)
【错题集-编程题】删除相邻数字的最大分数(动态规划 - 线性 dp)
|
8月前
【编程题-错题集】连续子数组最大和(动态规划 - 线性 dp)
【编程题-错题集】连续子数组最大和(动态规划 - 线性 dp)
|
8月前
|
算法 测试技术 C#
【线段树 区间位运算模板】3117划分数组得到最小的值之和
【线段树 区间位运算模板】3117划分数组得到最小的值之和
|
8月前
|
算法 测试技术 C#
【动态规划】【数论】【区间合并】3041. 修改数组后最大化数组中的连续元素数目
【动态规划】【数论】【区间合并】3041. 修改数组后最大化数组中的连续元素数目
|
8月前
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
56 0