序列--(树状数组维护等差数列模板)
题目描述
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
**/