士兵杀敌(五)

时间限制: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取余后输出
样例输入
  1. 5 3 2
  2. 1 3 2
  3. 2 4 1
  4. 5 5 10
  5. 1 5
  6. 2 3
样例输出
  1. 19
  2. 6

题目链接

一开始尝试线段树,超时,代码:

  1. #include<stdio.h>
  2. typedef struct NODE
  3. {
  4. int left, right;
  5. int count;
  6. int sum;
  7. }Node;
  8. Node array[4000000];
  9.  
  10. void buildTree(int root, int left, int right)
  11. {
  12. array[root].left = left;
  13. array[root].right = right;
  14. if(left < right)
  15. {
  16. buildTree(root * 2, left, (left + right) / 2);
  17. buildTree(root * 2 + 1, (left + right) / 2 + 1, right);
  18. }
  19. }
  20. void add(int root, int left, int right, int count)
  21. {
  22. if(array[root].left == left && array[root].right == right)
  23. {
  24. array[root].count += count;
  25. return ;
  26. }
  27. else
  28. {
  29. array[root].sum += count * (right - left + 1);
  30. if(right < (array[root].left + array[root].right ) / 2 + 1)
  31. add(root * 2, left, right, count);
  32. else if(left > (array[root].left + array[root].right ) / 2)
  33. add(root * 2 + 1, left, right, count);
  34. else
  35. {
  36. add(root * 2, left, (array[root].left + array[root].right ) / 2, count);
  37. add(root * 2 + 1, (array[root].left + array[root].right ) / 2 + 1, right, count);
  38. }
  39. }
  40. }
  41. int getSum(int root, int left, int right)
  42. {
  43. if(array[root].left == left && array[root].right == right)
  44. return array[root].sum + array[root].count * ( right - left + 1);
  45. if(array[root].count != 0)
  46. {
  47. add(root * 2, array[root].left , (array[root].left + array[root].right) / 2, array[root].count );
  48. add(root * 2 + 1, (array[root].left + array[root].right) / 2 + 1, array[root].right, array[root].count );
  49. array[root].sum += array[root].count * (array[root].right - array[root].left + 1);
  50. array[root].count = 0;
  51. }
  52. if(left > (array[root].left + array[root].right ) / 2)
  53. return getSum(root * 2 + 1, left, right);
  54. else if(right < (array[root].left + array[root].right ) / 2 + 1)
  55. return getSum(root * 2, left, right);
  56. else
  57. return getSum(root * 2 , left, (array[root].left + array[root].right ) / 2) + getSum(root * 2 + 1, (array[root].left + array[root].right ) / 2 + 1, right);
  58. }
  59. void insert(int root, int i, int num)
  60. {
  61. array[root].sum += num;
  62. if(array[root].left == array[root].right )
  63. {
  64. return ;
  65. }
  66. if(i > (array[root].left + array[root].right ) / 2 )
  67. insert(root * 2 + 1, i, num);
  68. else
  69. insert(root * 2, i, num);
  70. }
  71.  
  72. int main()
  73. {
  74. // freopen("in.txt", "r", stdin);
  75. int n ,c , q;
  76. int i;
  77. scanf("%d%d%d", &n, &c, &q);
  78. buildTree(1, 1, n + 1);
  79.  
  80. int s, e, num;
  81. for(i = 1; i <= c; i++)
  82. {
  83. scanf("%d%d%d", &s, &e, &num);
  84. s ++;
  85. e ++;
  86. add(1, s, e, num);
  87. }
  88. for(i = 1; i <= q; i++)
  89. {
  90. scanf("%d%d", &s, &e);
  91. s ++;
  92. e ++;
  93. printf("%d\n",getSum(1, s, e));
  94. }
  95. return 0;
  96. }

后来在网上发现一种特殊的算法,因为本题的区间插入和查询是分开的,所以可以在插入时只在区间头和尾部加上一个增量记号,最后添加操作结束后一次性修改所有的区间,然后再遍历一遍数组修改成前N个数的和, 最后可以O(1)时间求解,总体时间复杂度为O(N).AC代码:

  1. #include<stdio.h>
  2. int array[1000010];
  3. int main()
  4. {
  5. int n, c, q;
  6. scanf("%d%d%d", &n, &c, &q);
  7. int i;
  8. int s, e, num;
  9. for(i = 0; i < c; i++)
  10. {
  11. scanf("%d%d%d", &s, &e, &num);
  12. array[s] += num;
  13. array[e + 1] -= num;
  14. }
  15. //第一遍把标记下的增量修改到没一个人身上
  16. for(i = 0; i <= n; i++)
  17. {
  18.  
  19. array[i] += array[i - 1];
  20. }
  21.  
  22. //第二遍求出前N个人的和
  23. for(i = 0; i <= n; i++)
  24. {
  25. array[i] = (array[i] + array[i - 1]) % 10003;
  26. }
  27.  
  28. for(i = 0; i < q; i++)
  29. {
  30. scanf("%d %d", &s, &e);
  31. printf("%d\n", (array[e] - array[s - 1] + 10003) % 10003);//这里注意两个数都是10003的余数,相减要加上10003
  32. }
  33. return 0;
  34. }

NYOJ-228 士兵杀敌5的更多相关文章

  1. nyoj 228 士兵杀敌(五)

    题目: http://acm.nyist.net/JudgeOnline/problem.php?pid=228 由于该题一开始是进行士兵军功增加,最后才是查找士兵的军功总和,使用一个数组,进行延迟更 ...

  2. NYOJ 228 士兵杀敌(五) (模拟)

    {题目链接](http://acm.nyist.net/JudgeOnline/problem.php?pid=228) 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为0~M,每次有任务的时候 ...

  3. NYOJ 228 士兵杀敌(五)【差分标记裸题】

    题目链接 所有元素初始值为0才能这么做: ①l--r全加1 a[l]++; a[r+1]--; 求一遍前缀和为元素本身. 求两遍前缀和为元素前缀和. #include<cstdio> #i ...

  4. NYOJ 119 士兵杀敌(三) RMQ ST

    NYOJ 119 士兵杀敌(三) RMQ ST 题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=119 思路: ST在线 预处理O(nlog ...

  5. NYOJ 116 士兵杀敌 (线段树,区间和)

    题目链接:NYOJ 116 士兵杀敌 士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描写叙述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的 ...

  6. nyoj 108 士兵杀敌(一)

    点击打开链接 士兵杀敌(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师, ...

  7. NYOJ 123 士兵杀敌4-树状数组的插线求点

    士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编 ...

  8. nyoj 119 士兵杀敌(三)(RMQ)

    士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5   描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进 ...

  9. nyoj 119 士兵杀敌(三)【线段树区间最大值最小值差】

    士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5   描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进 ...

  10. nyoj 116 士兵杀敌(二)【线段树单点更新+求和】

    士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常 ...

随机推荐

  1. webstorm修改文件,webpack-dev-server不自动编译刷新的解决办法

    webstorm设置中,"Settings"--"Appearance & Behavior"--"System Settings" ...

  2. IOS开发-PCH文件的使用

    PCH文件存储一些共享的数据,在其他的文件可以直接使用,这样减少程序输入,比如存储宏定义 1.首先新建PCH文件 2.建立完毕 3.在这里找到文件路径 4.进入targets 点击Build Sttt ...

  3. js 字符串类型转为数组类型

    以前从来没有想过这个转换,以为直接拼出来就可以了,今天同事问我这个问题,特记录如下. var test='["colkey", "col", "col ...

  4. WSUS目录本地迁移

    生产环境中有一台win2003 server,安装了Microsoft Windows Server Update Services 3.0,作为所有windows server的内网补丁更新服务器, ...

  5. 设计模式的一些杂谈与反思---functionn和signals

    以下关于GOF的一些例子命名不是很准确,但是大概意思差不多,懒得再去翻书了 模拟观察者模式 模拟中介者模式 模拟command模式 模拟memento和command   模拟观察者模式 观察者与职责 ...

  6. HDU2829

    题目大意:给定一个长度为n的序列,至多将序列分成m+1段,每段序列都有权值,权值为序列内两个数两两相乘之和.m<=n<=1000. 分析:令w[i,j]表示区间[i,j]中两两乘积之和,f ...

  7. "unresolved external symbol __imp__WSACleanup@0"

    编译时出现这种问题怎么解决:"unresolved external symbol __imp__WSACleanup@0"出现此类问题一般是ws2_32.lib这个lib没有li ...

  8. 内存修改console

    #include <stdio.h> #include <windows.h> #include <winuser.h> int main() { int cur_ ...

  9. FlashBuilder(FB/eclipse) 打开多个无效

    FB也即Eclipse. 想要打开多个FB,只需要新建多个FB的快捷方式,然后在路径上面加上参数 -data "具体路径" 再打开即可. 如: "C:\Program F ...

  10. JavaScript正则详谈

    JavaScript RegExp 基础详谈   前言: 正则对于一个码农来说是最基础的了,而且在博客园中,发表关于讲解正则表达式的技术文章,更是数不胜数,各有各的优点,但是就是这种很基础的东西,如果 ...