POJ_3468(1)

在消化了PPT上思想之后,又重新做了一下这个题目。

不妨将原数组的元素记作a[i],然后我们用堆建立两棵线段树,一棵的原数组为x[i](x[i]=a[i]-a[i-1],即原数组的差分数组),另一棵的原数组为ix[i](ix[i] = i*x[i])。

为什么要这么做呢?原因如下。

如果我们记S[i]为x[i]的前缀和,我们会发现S[i]实际上就是a[i],也就是说差分的前缀和就等于原数组中的对应元素(因而才说差分是前缀和的逆运算)。我们不妨设SS[i]为S[i]的前缀和,在求区间和时用SS[b]–SS[a-1]自然是很方便的,然而对于修改操作,无论是维护S[i]还是SS[i]都会很麻烦,但恰恰是维护x[i]很简单,只需要修改两个值,x[a]和x[b+1]。

那么能不能将两个方便之处统一到一起呢?当然可以,因为SS[n] = (n+1)*(x[1]+x[2]+…+x[n])-(1*x[1]+2*x[2]+…+n*x[n]),而i*x[i]自然就是前面提的ix[i]咯,于是我们只要维护x[i]和ix[i]即可,这样在修改的时候每次只需各修改两个值,并修改相应的祖先即可,于是把区间修改的复杂度降成了元素修改的复杂度。

查询区间和的时候只需要用线段树求x[i]与ix[i]的前缀和并做一定运算即可。

#include<stdio.h>#include<string.h>#define MAXD 100010int N, Q, M;long long int a[MAXD], x[4 * MAXD], ix[4 * MAXD];char op[5];void init(){int i, j;for(M = 1; M < N + 2; M <<= 1);    a[0] = 0;for(i = 1; i <= N; i ++)        scanf("%lld", &a[i]);for(i = N; i >= 1; i --)        a[i] -= a[i - 1];    memset(x, 0, sizeof(x));    memset(ix, 0, sizeof(ix));for(i = 1, j = M + 1; i <= N; i ++, j ++)    {        x[j] = a[i];        ix[j] = i * a[i];    }for(i = M - 1; i > 0; i --)    {        x[i] = x[i * 2] + x[i * 2 + 1];        ix[i] = ix[i * 2] + ix[i * 2 + 1];    }}void solve(){int i, j, a, b, c;    scanf("%s", op);if(op[0] == 'C')    {        scanf("%d%d%d", &a, &b, &c);        a = a + M;        x[a] += c, ix[a] += (a - M) * c;for(; a ^ 1; a >>= 1)        {            x[a >> 1] = x[a] + x[a ^ 1];            ix[a >> 1] = ix[a] + ix[a ^ 1];        }        b = b + M + 1;        x[b] -= c, ix[b] -= (b - M) * c;for(; b ^ 1; b >>= 1)        {            x[b >> 1] = x[b] + x[b ^ 1];            ix[b >> 1] = ix[b] + ix[b ^ 1];        }    }else    {        scanf("%d%d", &a, &b);int s, t;long long int sum1, sum2, res;        sum1 = sum2 = 0;        s = M, t = a + M;for(; s ^ t ^ 1; s >>= 1, t >>= 1)        {if(~s & 1)                sum1 += x[s ^ 1], sum2 += ix[s ^ 1];if(t & 1)                sum1 += x[t ^ 1], sum2 += ix[t ^ 1];        }        res = - a * sum1 + sum2;        sum1 = sum2 = 0;        s = M, t = b + M + 1;for(; s ^ t ^ 1; s >>= 1, t >>= 1)        {if(~s & 1)                sum1 += x[s ^ 1], sum2 += ix[s ^ 1];if(t & 1)                sum1 += x[t ^ 1], sum2 += ix[t ^ 1];        }        res += (b + 1) * sum1 - sum2;        printf("%lld\n", res);    }}int main(){while(scanf("%d%d", &N, &Q) == 2)    {        init();for(int i = 0; i < Q; i ++)            solve();    }return 0;}

转载于:https://www.cnblogs.com/staginner/archive/2011/11/01/2231563.html

POJ 3468 A Simple Problem with Integers (1)相关推荐

  1. 【线段树】【模板】讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值)

    [线段树][模板]讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值) ...

  2. poj 3468 A Simple Problem with Integers(线段树区区)

    题目链接:  http://poj.org/problem?id=3468 题目大意:  给出N个数,和M次查询 C a b c  区间[a,b]的值都加上c Q a b     查询区间[a,b]值 ...

  3. POJ 3468 A Simple Problem with Integers(线段树:区间更新)

    http://poj.org/problem?id=3468 题意: 给出一串数,每次在一个区间内增加c,查询[a,b]时输出a.b之间的总和. 思路: 总结一下懒惰标记的用法吧. 比如要对一个区间范 ...

  4. POJ 3468 A Simple Problem with Integers

    分析:这题wa了好多次(看了下discuss好多人也是这样,好题~).一处是sum值会超int32,要用int64.还有一处是toadd要累加,我不知道是受上一题影响还是怎的..pushdown的时候 ...

  5. POJ - 3468 A Simple Problem with Integers(分块)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列,再给出 m 次操作,每次操作分为两种情况: C l r d:区间 [ l , r ] 内的数字都加上 d Q l r :查询 [ l , r ...

  6. POJ 3468 A Simple Problem with Integers(线段树区间更新)

    题目链接 这个真费劲...其实我也不懂 为什么...大体思想是,如果把区间更新了,开始的时候只把用懒惰标记标记那个区间,而不更新底层元素,而如果查询的时候顺带着把lz标记给消除...多敲几遍,多调试一 ...

  7. poj 3243:A Simple Problem with Integers

    3243:A Simple Problem with Integers 查看 提交 统计 提示 提问 总时间限制:  5000ms  单个测试点时间限制:  2000ms  内存限制:  131072 ...

  8. 线段树专辑—— pku 3468 A Simple Problem with Integers

    http://poj.org/problem?id=3468 典型的一道基于lazy传递的线段树题目,这题和一般题目不同的地方在于,它的每次操作不是简单的覆盖线段,而是累加.记得第一次写的时候纠结了好 ...

  9. poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)

    1 /* 2 树状数组第三种模板(改段求段)不解释! 不明白的点这里:here! 3 */ 4 #include<iostream> 5 #include<cstring> 6 ...

最新文章

  1. 虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机(修改.vmx文件virtualHW.version = “xx“字段)
  2. Php输出Xml报错:XML declaration allowed only at the start of the document
  3. mock模拟接口测试 vue_在 Vue-CLI 中引入 simple-mock实现简易的 API Mock 接口数据模拟...
  4. 1+X web中级 Laravel学习笔记——使用DB facade对数据库进行增删改查
  5. linux删除副本文件,RMAN不能删除控制文件副本解决
  6. eclipse设置内存参数 堆内存溢出
  7. zabbix-2.0.8日常巡检-检测项目状态
  8. 在兼职的情况下,有什么办法可以在年底之前挣5000到一万块?
  9. 2019北京国际智慧城市、物联网、大数据博览会
  10. 看书看困了,写几句提提精神
  11. 工作中使用到的单词(软件开发)
  12. 【高中数学】数列 · 通项求法
  13. 数字化转型的趋势、挑战与战略
  14. python glob.glob使用
  15. 潜匿的怪物,你的供应链真的安全吗?
  16. C#字符串操作,转自韩迎龙博客
  17. 使用FFmpeg转换mp3或wav文件为pcm格式文件
  18. python 实现聊天室
  19. 001:你好Direct 2D! 在对话框中初次使用D2D
  20. jquery css3问卷答题卡翻页动画效果

热门文章

  1. /usr/include/boost/type_traits/detail/has_binary_operator.hp:50: Parse error at BOOST_JOIN错误
  2. spring-mybatis.xml 访问html5,Spring mvc无xml配置及利用JdbcTemplate访问数据库
  3. taro压缩_Taro 如何开始微信小程序的开发
  4. 计算机怎么恢复上一步,电脑怎么还原系统 电脑还原系统步骤盘点
  5. java反射比较两个model6_java反射机制
  6. linux重定向文件不存在,shell 12 21 filename重定向的含义和区别
  7. 2021.12.20用ULN2003驱动四线步进电机
  8. asynchttpclient 超时_深圳拟出台标准:外卖配送超时,要补偿消费者
  9. Java锁 优先级_详解Java的线程的优先级以及死锁
  10. python爬虫自学笔记分析解密_python爬虫学习笔记——1 各种文本分析工具简介之汇总...