等差数列
描述
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
",ans);
}