luogu P1719 最大加权矩形
题目大意
需要支持在一个序列中插入等差数列
需要插入\(O(1)\) 最终统计答案\(O(n)\)
\(1\leq n\leq 1e7\)
Sol
对于一个序列如下:
0 | 0 | 4 | 6 | 8 | 10 | 12 | 0 | 0 |
---|
我们将其进行一次差分,可以得到:
0 | 0 | 4 | 2 | 2 | 2 | 2 | -12 | 0 |
---|
可以发现中间出现了一串公差,在差分一次:
0 | 0 | 4 | -2 | 0 | 0 | 0 | -14 | 12 |
---|
应该可以看出来,给定的四个数 \(l\),\(r\),\(s\),\(e\)以及公差\(d=\frac{e-s}{r-l}\)
其实就是在差分数组\(d\)中将
- \(d_l\) 加 \(s\)
- \(d_{l+1}\) 加 \(d-s\)
- \(d_{r+1}\) 减 \(d+e\)
- \(d_{r+2}\) 加 \(e\)
最后进行两次差分即可
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e7+10;
int n , m;
LL sum1[N] , sum2[N];
int main() {
scanf("%d%d" , &n , &m);
for(int i = 1 ; i <= m ; i ++) {
LL l , r , s , e , d = 0;
scanf("%lld%lld%lld%lld" , &l , &r , &s , &e);
if(r != l) d = (e-s)/(r-l);
sum1[l] += s; sum1[l+1] += d-s;
sum1[r+1]-=d+e; sum1[r+2]+=e;
}
LL res1 = 0 , res2 = 0;
for(int i = 1 ; i <= n ; i ++) {
sum1[i] += sum1[i-1];
sum2[i] = sum2[i-1] + sum1[i];
res1 ^= sum2[i];
if(sum2[i] > res2) res2 = sum2[i];
}
printf("%lld %lld\n" , res1 , res2);
return 0;
}