C. Producing Snow (二分, 前缀和)

  • 题目链接:http://codeforces.com/contest/948/problem/C
  • 题意:给你个数字n 表示有n天。每天堆起大小为 v[i] 的雪堆,每天的温度分别为 t[i] , 每天对于每个雪堆,会融化 t[i] 的雪。求每天分别总共要融化多少雪?
  • 数据大小:1 <= n <= 1e5, 1 <= v[i], t[i] <= 1e9, 时限:1s
  • 思路:n为1e5 时限1s,O( n 2 )肯定是不行了。来想想O(nlogn)的方法:
    • 在第i天,对于v[i] 我可以求出他在第idx天彻底融化,并且那天融化了的不足t[idx]的雪是多少:
      • int idx = upper_bound(sum+1, sum+1+n, v[i]+sum[i-1]) - sum;
      • ans[idx] += v[i]+sum[i-1] - sum[idx-1];
    • 并且,从今天(第i天)到 第idx-1天,不会彻底融化的雪堆+1,在第idx天不会彻底融化的雪堆-1
      • sig[i]++; sig[idx]–;
    • 则第i天融化的雪量为 前i项的sig[i] 之和* t[i] + ans[i]

#include <bits/stdc++.h>
#define pi acos(-1)
#define se second
#define fi first
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 1e9+7;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1e5+9;;
const LL mod = 1e9+7;

int v[maxn], t[maxn], sig[maxn];
LL sum[maxn], ans[maxn];
int main()
{
    int n;scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%d", &v[i]);
    }
    for(int i=1; i<=n; i++){
        scanf("%d", &t[i]);
        sum[i] = sum[i-1]+t[i];
    }
    for(int i=1; i<=n; i++){
        int idx = upper_bound(sum+1, sum+1+n, v[i]+sum[i-1]) - sum;
        ans[idx] += v[i]+sum[i-1] - sum[idx-1];
        sig[i]++;
        sig[idx]--;
    }
    LL SIG = 0;
    for(int i=1; i<=n; i++){
        SIG += sig[i];
        printf("%I64d ", ans[i]+SIG*t[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37352710/article/details/81739421