洛谷 P1672

前缀和

降低区间和查询问题时间复杂度,一维和二维

一种数据预处理手段,一般配合其他算法查分、二分搜索

二分:容斥原理。

sum[i][j] = sum[i - 1][j] +sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];

差分

前缀和相对的策略,可当做求和的逆运算

a[l]++; a[r + 1]--;

洛谷 P1672

https://www.luogu.com.cn/problem/P1672

牛的个数: C

收到运来的饲料: F1

到 D 天为止

剩下饲料:F2

判断饲料最近一次运到的时候

原理:F1 + ( D 天到 x 天的和 ) = F2

输入数据,差分记录

cin >> c >> f1 >> f2 >> d;
for (int i = 1; i <= n; ++ i ) {
	int l, r;
	cin >> l >> r;
	ll = min(ll, l);
	rr = max(rr, r);
	diff[l]++;
	diff[r + 1]--;
}

差分转前缀

for (int i = ll; i <= rr; ++ i) {
	sum[i] = sum[i - 1] + diff[i];
}

时间从后往前推,算出最近的,加sum[i]的数,使数达到F1

int x = d + 1; //天数
while (f1 != f2) {
	// f2 += sum[--x]; 优化
	f2 += sum[x];
	x--;
}

输出

cout << x;

完整代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;

int c, f1, f2, d, a[N], sum[N], rr = -INT_MAX, ll = INT_MAX;

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> c >> f1 >> f2 >> d;
  for (int i = 1; i <= c; ++i) {
    int l, r;
    cin >> l >> r;
    a[l]++;
    a[r + 1]--;
    ll = min(ll, l);
    rr = max(rr, r);
  }
  for (int i = ll; i <= rr; ++i) {
    sum[i] = sum[i - 1] + a[i];
  }
  int x = d + 1;
  while (f2 != f1) {
    f2 += sum[--x];
  }
  cout << x;
}
posted @ 2024-09-28 22:10  Mono_Awen  阅读(33)  评论(0)    收藏  举报