士兵杀敌5 前缀数组

士兵杀敌(五)

时间限制:2000 ms  |  内存限制:65535 KB
难度:5
 
描述

南将军麾下有百万精兵,现已知共有M个士兵,编号为0~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情。

在这样的情况下,南将军却经常会在许多次战役之后询问军师小工第i号士兵到第j号士兵所有人的总军功数。

请你帮助军师小工回答南将军的提问。

 
输入
只有一组测试数据
第一行是三个整数N,C,Q(1<=N,C,Q<=1000000),其中N表示士兵的总数。
随后的C行,每行有三个整数Mi,Ni,Ai(0<=Mi<=Ni<=N,0<=Ai<=100),表示从第Mi号到第Ni号士兵所有人平均增加了Ai的军功。
再之后的Q行,每行有两个正正数m,n,表示南将军询问的是第m号士兵到第n号士兵。
输出
请对每次询问输出m号士兵到第n号士兵的总军功数,由于该数值可能太大,请把结果对10003取余后输出
样例输入
5 3 2
1 3 2
2 4 1
5 5 10
1 5
2 3
样例输出
19
6

线段树代码: 超时
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<queue>
#include<deque>
#include<iomanip>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<fstream>
#include<memory>
#include<list>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 1000002
#define L 31
#define INF 1000000009
#define eps 0.00000001
struct node
{
    int l, r, data;
}T[MAXN*4+10];
int n,c,q,a[MAXN];
/*
int Query(int p, int k)
{
    if (T[p].l == T[p].r)
        return T[p].data;
    int mid = (T[p].l + T[p].r) >> 1;
    int sum = T[p].data;
    if (k <= mid)
        sum += Query(p << 1, k);
    else
        sum += Query(p << 1 | 1, k);
    return sum;
}
*/
int Query(int p, int l, int r)
{
    //cout <<":::::::::"<<T[p].l<< ' '<<T[p].r<<' '<<T[p].data << endl;
    if (T[p].l == T[p].r)
        return T[p].data;
    int mid = (T[p].l + T[p].r) >> 1;
    int sum;
    if (l <= T[p].l&&r >= T[p].r)
        sum = (T[p].r - T[p].l + 1)*T[p].data;
    else
        sum = (min(T[p].r, r) - max(T[p].l, l) + 1) * T[p].data;
    if (r <= mid)
        sum += Query(p << 1, l, r);
    else if (l > mid)
        sum += Query(p << 1 | 1, l, r);
    else
    {
        sum += Query(p << 1, l, mid);
        sum += Query(p << 1 | 1, mid + 1, r);
    }
    //cout<<' '<<sum<<endl;
    return sum;
}
void Build(int p, int l, int r)
{
    T[p].l = l, T[p].r = r, T[p].data = 0;
    if (l == r)
    {
        T[p].data = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    Build(p << 1, l, mid);
    Build(p <<1 | 1, mid + 1, r);
}
void Insert(int p, int l, int r, int num)
{
    //cout << p << ' ' << l << ' ' << r << ' ' << num << endl;
    if (l <= T[p].l&&r >= T[p].r)
    {
        T[p].data += num;
        return;
    }
    int mid = (T[p].l + T[p].r) / 2;
    if (r <= mid)
        Insert(p << 1, l, r, num);
    else if (l > mid)
        Insert(p << 1 | 1, l, r, num);
    else
    {
        Insert(p << 1, l, mid, num);
        Insert(p << 1 | 1, mid + 1, r, num);
    }
}
int main()
{
    int t1, t2, t3;
    while (scanf("%d%d%d", &n, &c, &q) != EOF)
    {
        memset(a, 0, sizeof(a));
        Build(1, 1, n);
        while (c--)
        {
            scanf("%d%d%d", &t1, &t2, &t3);
            Insert(1, t1, t2, t3);
        }
        while (q--)
        {
            scanf("%d%d", &t1, &t2);
            printf("%d
", Query(1, t1, t2));
        }
    }
    return 0;
}

利用前缀数组!巧妙!

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
//#define LOCAL
const int MAXN = 1000010;
const int MOD = 10003;
int m[MAXN];
int main() {
#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    int N, C, Q;
    scanf("%d%d%d", &N, &C, &Q);
    memset(m, 0, sizeof(m));
    int a, b, c;
    while (C--) {
        scanf("%d%d%d", &a, &b, &c);
        m[a] += c; m[b + 1] -= c;
    }
    for (int i = 1; i <= N; i++)m[i] += m[i - 1];
    for (int i = 1; i <= N; i++)m[i] = (m[i] + m[i - 1]) % MOD;
    while (Q--) {
        scanf("%d%d", &a, &b);
        printf("%d
", (m[b] - m[a - 1] + MOD) % MOD);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/joeylee97/p/6875513.html