等差数列
描述
Geobiyye 是一个喜欢数据结构的女孩子。
Geobiyye 给了你一个长度为 \(n\) 的序列 \(a_i\) ,序列中每个元素的初始值为 \(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 只想要知道最终序列每一项的异或和
数据范围
对于 100%的数据: \(n,m≤500000, 1≤l<r≤n\)。
题解
恼,现在我连普及组题都只能打个暴力了
看到 \(500000\) 就知道其实和数据结构没啥关系
然后中途没有询问,只问完整的,可以用差分
因为如果只有一层的前缀和的话差分依旧需要每个点都搞一次,所以我们考虑两层的前缀和
用 \(d\) 表示公差,则我们希望第二层的前缀和是这样的:\(s,s+d,s+2d,...,e,0,0\)
那么第一层的前缀和可以是这样的:\(s,d,d,...,d,-e,0\)
于是,我们构造出来原本的差分数组:
\(s,d-s,0,...,0,-d-e,e\)
这样构造完,代码就很简洁了:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[500010];
int pre[500010],pre2[500010];
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;++i){
int l,r,s,e;
scanf("%lld%lld%lld%lld",&l,&r,&s,&e);
int d=(e-s)/(r-l);
a[l]+=s,a[l+1]+=-s+d,a[r+1]+=-d-e,a[r+2]+=e;
}
int ans=0;
for(int i=1;i<=n;++i){
pre[i]=pre[i-1]+a[i];
pre2[i]=pre2[i-1]+pre[i];
ans^=pre2[i];
}
printf("%lld\n",ans);
}