题意

题目链接

Sol

好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0)

一个很显然的思路是考虑每个最小值的贡献。

预处理出每个数左边第一个比他小的数,右边第一个比他大的数。

那么\([L_i + 1, i]\)对\([i, R_i]\)中的每个数都会有\(a[i]\)的贡献。

我们可以抽象成一个二维平面内的矩形加。

询问就是询问最下角为\((l, l)\),右上角为\((r, r)\)的矩形内的权值

也就是我们需要解决这么一个问题:两个操作, 矩形加矩形求和,而且前者都在后者的前面执行

我们可以把所有矩形加操作全都向右上角差分,所有询问操作全都向左下角差分。这样我们就只需要考虑每个\((i, j)\)左下角的所有修改\((x, y)\)的影响,这部分的权值为\((i - x + 1) * (j - y + 1) * w\)

直接拆开,发现可以用树状数组维护(单点修改,查前缀和)。然后就做完了

复杂度\(O(nlogn)\)

  1. /*
  2. */
  3. #include<bits/stdc++.h>
  4. #define LL long long
  5. #define fi first
  6. #define se second
  7. #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
  8. char buf[(1 << 22)], *p1 = buf, *p2 = buf;
  9. char obuf[1<<24], *O = obuf;
  10. void print(int x) {if(x > 9) print(x / 10); *O++ = x % 10 + '0';}
  11. #define OS *O++ = '\n';
  12. #define fout fwrite(obuf, O-obuf, 1 , stdout);
  13. using namespace std;
  14. const int MAXN = 1e5 + 10, INF = 1e9 + 10;
  15. template<typename A, typename B> inline bool chmax(A &x, B y) {return x < y ? x = y, 1 : 0;}
  16. template<typename A, typename B> inline bool chmin(A &x, B y) {return x > y ? x = y, 1 : 0;}
  17. inline int read() {
  18. char c = getchar(); int x = 0, f = 1;
  19. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
  20. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  21. return x * f;
  22. }
  23. int N, M, Q, a[MAXN], st[MAXN], L[MAXN], R[MAXN];
  24. LL ans[MAXN];
  25. struct Modify {
  26. int h;LL v;
  27. };
  28. vector<Modify> tag[MAXN];
  29. struct Query {
  30. int h, id, opt;
  31. };
  32. vector<Query> q[MAXN];
  33. void Add(int x1, int y1, int x2, int y2, int v) {
  34. tag[x1].push_back({y1, v});
  35. tag[x2 + 1].push_back({y1, -v});
  36. tag[x1].push_back({y2 + 1, -v});
  37. tag[x2 + 1].push_back({y2 + 1, v});
  38. }
  39. void Query(int x1, int y1, int x2, int y2, int id) {
  40. q[x2].push_back({y2, id, 1});
  41. q[x1 - 1].push_back({y2, id, -1});
  42. q[x2].push_back({y1 - 1, id, -1});
  43. q[x1 - 1].push_back({y1 - 1, id, 1});
  44. }
  45. #define lb(x) (x & (-x))
  46. LL s1[MAXN], s2[MAXN], s3[MAXN], s4[MAXN];
  47. void TreeAdd(int x, LL v1, LL v2, LL v3, LL v4) {
  48. while(x <= M)
  49. s1[x] += v1, s2[x] += v2, s3[x] += v3, s4[x] += v4, x += lb(x);
  50. }
  51. pair<pair<LL, LL>, pair<LL, LL> > TreeQuery(int x) {
  52. pair<pair<LL, LL>, pair<LL, LL> > ans;
  53. while(x)
  54. ans.fi.fi += s1[x], ans.fi.se += s2[x], ans.se.fi += s3[x], ans.se.se += s4[x], x -= lb(x);
  55. return ans;
  56. }
  57. #undef lb
  58. void solve() {
  59. for(int i = 1; i <= M; i++) {
  60. for(auto y: tag[i]) {
  61. int v = y.v;
  62. TreeAdd(y.h, 1ll * v, 1ll * (y.h - 1) * v, 1ll * (i - 1) * v, 1ll * (y.h - 1) * (i - 1) * v);
  63. }
  64. for(auto x : q[i]) {
  65. LL sumv = 0, sumyv = 0, sumxv = 0, sumxyv = 0;
  66. pair<pair<LL, LL>, pair<LL, LL> > tmp = TreeQuery(x.h);
  67. sumv = tmp.fi.fi;
  68. sumyv = tmp.fi.se;
  69. sumxv = tmp.se.fi;
  70. sumxyv = tmp.se.se;
  71. int j = x.h;
  72. ans[x.id] += 1ll * x.opt * (1ll * i * j * sumv - 1ll * i * sumyv - 1ll * j * sumxv + sumxyv);
  73. }
  74. }
  75. }
  76. void Pre() {
  77. a[0] = -INF; a[N + 1] = -INF; int top = 0;
  78. for(int i = 1; i <= N + 1; i++) {
  79. while(top && a[i] < a[st[top]]) R[st[top--]] = i;
  80. L[i] = st[top];
  81. st[++top] = i;
  82. }
  83. for(int i = 1; i <= N; i++)
  84. if((i <= R[i] - 1) && (L[i] + 1 <= i))
  85. Add(i, L[i] + 1, R[i] - 1, i, a[i]);
  86. }
  87. signed main() {
  88. //freopen("a.in", "r", stdin); freopen("b.out", "w", stdout);
  89. N = read(); M = N + 1; Q = read();
  90. for(int i = 1; i <= N; i++) a[i] = read();
  91. Pre();
  92. for(int i = 1; i <= Q; i++) {
  93. int l = read(), r = read(), ans = 0;
  94. Query(l, l, r, r, i);
  95. }
  96. solve();
  97. for(int i = 1; i <= Q; i++) cout << ans[i] << '\n';
  98. return 0;
  99. }

洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)的更多相关文章

  1. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

  2. [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)

    [NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...

  3. BZOJ3262/洛谷P3810 陌上花开 分治 三维偏序 树状数组

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 洛谷P3810 题意 有$n$个元素,第 ...

  4. 洛谷 P4396 (离散化+莫队+树状数组)

    ### 洛谷P4396  题目链接 ### 题目大意: 有 n 个整数组成的数组,m 次询问,每次询问中有四个参数 l ,r,a,b .问你在[l,r] 的区间内的所有数中,值属于[a,b] 的数的个 ...

  5. D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]

    题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...

  6. 【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)

    点此看题面 大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标. 关于整体二 ...

  7. 洛谷 P5057 [CQOI2006]简单题(树状数组)

    嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ...

  8. 洛谷P4054 [JSOI2009]计数问题(二维树状数组)

    题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...

  9. 模板【洛谷P3368】 【模板】树状数组 2

    P3368 [模板]树状数组 2 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 树状数组区间加,单点查询. code: #include <i ...

随机推荐

  1. 微信小程序的概要

    微信小程序的概要 学习小程序要了解一下什么事小程序,小程序开发前需要做哪些准备,微信小程序开发工具的使用,小程序中的目录结构解析,视图和渲染,事件. 小程序的配置详解,小程序的生命周期与app对象的使 ...

  2. Java回调机制总结

    调用和回调机制 在一个应用系统中, 无论使用何种语言开发, 必然存在模块之间的调用, 调用的方式分为几种: 1.同步调用 同步调用是最基本并且最简单的一种调用方式, 类A的方法a()调用类B的方法b( ...

  3. vim常用命令行备忘总结

    一 窗口切换 1 :sp    水平切换当前窗口 2 :vsp 垂直切换当前窗口 3 :clo 关闭活动窗口 4 : on 只保留活动窗口 5 : ctrl + w  在窗口间循环切换  ctrl + ...

  4. gdb调试的layout使用

    layout:用于分割窗口,可以一边查看代码,一边测试.主要有以下几种用法:layout src:显示源代码窗口layout asm:显示汇编窗口layout regs:显示源代码/汇编和寄存器窗口l ...

  5. 深入理解Java Stream流水线

    前面我们已经学会如何使用Stream API,用起来真的很爽,但简洁的方法下面似乎隐藏着无尽的秘密,如此强大的API是如何实现的呢?Pipeline是怎么执行的,每次方法调用都会导致一次迭代吗?自动并 ...

  6. ZOJ Problem Set - 1730 Crazy Tea Party

    #include<cstdio> int main(){ int T,n; scanf("%d",&T); while(T--){ scanf("%d ...

  7. JavaScript高级编程(1)——JavaScript初识

    一.javascript的简介 1.1 javascript的历史回顾. Javascript诞生于1995年.当时,它主要的目的是用来处理一些由服务器端处理的输入验证操作.在javascript没有 ...

  8. Apache-Flink深度解析-SQL概览

    你可能感兴趣的文章: Flink入门 Flink DataSet&DataSteam API Flink集群部署 Flink重启策略 Flink分布式缓存 Flink重启策略 Flink中的T ...

  9. springmvc 项目完整示例09 maven项目创建

    需求表均同springmvc案例 此处只是使用maven 注意,以下所有需要建立在你的eclipse等已经集成配置好了maven了,说白了就是新建项目的时候已经可以找到maven了 没有的话需要安装m ...

  10. SOAP系列目录

    1.协议分析 2.WebService.WCF介绍 3.HttpClientHelper实现webservice调用 4.SoapCore介绍