士兵杀敌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\n", 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\n", (m[b] - m[a - 1] + MOD) % MOD);
    }
    return 0;
}

时间: 2024-10-10 07:48:53

士兵杀敌5 前缀数组的相关文章

NYOJ116 士兵杀敌(二)【树状数组】

士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧. 南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数. 输入 只有一组测试数据 第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数.(1<M<1000

士兵杀敌(四)(树状数组+线段树)

士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧. 假设起始时所有人的军功都是0. 输入

NYOJ108 士兵杀敌(一)【树状数组】

士兵杀敌(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军现在想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧. 注意,南将军可能会问很多次问题. 输入 只有一组测试数据 第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示南将军询问的次数(1<M<100000) 随后的一行是N个整数,ai表示第i号士兵杀敌数

士兵杀敌1(树状数组)

首先,要先讲讲树状数组: 树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值. 假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别. 来观察上面的图: 令

NYOJ 116士兵杀敌(二) 树状数组

士兵杀敌(一) 数组是固定的,所以可以用一个sum数组来保存每个元素的和就行,但是不能每次都加,因为那样会超时,查询次数太多.但是这个士兵杀敌(二)就不能用那个方法来解了,因为这个是动态的,中间元素的值可能会变化,所以引出一个新的东西来.刚开始想了一下,实在是没有想到方法,就去讨论区看了看,一看好像都说用树状数组,就去找树状数组的用法. 先上图,看着图解释容易理解点. 数组A是原数组中的元素,数组C是树状数组中的元素,图中C数组的元素组成为A中的某些元素之和,这些元素的个数取决于它的下标能被多少

【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)

[概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识,当初A的第一个数据结构的题就是关于树状数组的,忘了忘了.. Problem C: candy Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 252  Solved: 63 SubmitStatusWeb Board Description Kimi

NYOJ 士兵杀敌(1~5)

士兵杀敌(1): http://acm.nyist.net/JudgeOnline/problem.php?pid=108 分析:前缀和 1 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 int a[1000005]; 7 int sum[1000005]; 8 9 int main() 10 { 11 int n,m; 12 scanf("%d%d",&n,&m); 13 14 sum[0]

nyoj 123 士兵杀敌(四)

士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧. 假设起始时所有人的军功都是0. 输入

士兵杀敌(一)

题目来源 士兵杀敌(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军现在想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧. 注意,南将军可能会问很多次问题. 输入 只有一组测试数据 第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示南将军询问的次数(1<M<100000) 随后的一行是N个整数,ai表示第i号