前缀和
前缀和定义;s[0]=0;
s[i]=s[i-1]+a[i];
其中s[i]数组为a[i]数组的前缀和;
有了前缀和后,给定一个区间 [l,r] 的和就可以表示为;
sum=s[r] -s[l-1];
代码:
cin >> n >> m ;
s[0] = 0;
for (int i = 1; i <= n; i++)
s[i] = s[i - 1] + a[i];//求前缀和
bool re = true;
for (int i = 1; i <= m; i++)
{
unsigned long long x = l[i], y = r[i];
unsigned long long sum = s[y] - s[x - 1];
if (re)
{
re = false;
ans = sum;
}
else
ans =ans^ sum;
}
差分
对于一个给定的数列A,它的差分数列B定义为:
B[1]=A[1,B[]=A[i]-A[t-1(2≤i≤n)
容易发现,“前缀和”与“差分”是一对互逆运算,差分序列B的前缀和序列就是
原序列A,前缀和序列S的差分序列也是原序列A
把序列A的区间[l,r]加d(即把A,A+1,…,A都加上d),其差分序列B的变
化为B[l]加d,B[r+1]减d,其他位置不变。这有助于我们在很多题目中,把原序列上
的“区间操作”转化为差分序列上的“单点操作”进行计算,降低求解难度。
代码:
cin >> n >> m >> seed;
s[1] = a[1];
for (int i = 2; i <= n; i++)//差分
s[i] = a[i] - a[i - 1];
s[n + 1] = 0;
for (int i = 1; i <= m; i++)
{
int L = l[i], R = r[i], q = p[i];
s[L] -= q, s[R + 1] += q;//差分
}
a[1] = s[1];
for (int i = 2; i <= n; i++)//前缀和
a[i] = a[i - 1] + s[i];
for (int i = 1; i <= n; i++)
{
if (a[i] < 0)
a[i] = 0;
ans = ans ^ a[i];
}
cout << ans << endl;
return 0;