题目链接HDU 6989

题意:
有一个序列 {ana_nan​} 给定m个询问,每次给定 l,rl,rl,r ,随机在 [l,r][l,r][l,r] 中选出一个子区间,计算平均值。这里平均值的定义为 (max{al,...,ar}+min{al,...,ar})/2(max\{a_l, ... , a_r\} + min \{a_l, ..., a_r \}) / 2(max{al​,...,ar​}+min{al​,...,ar​})/2,求[l,r][l,r][l,r]平均值的期望。

思考:
首先该问题的平均值可以分为最大值和最小值来分别求。
这道题如果只是单纯的考虑[1,n][1,n][1,n],那么就是一个经典的单调栈维护每个 aia_iai​ 的为最值的区间。
但是考虑对于有多个询问,我们考虑如何来实现。
我们离线该问题,然后依旧采用枚举右端点,然后去查询左端点的方式来解决问题。
如果对于每个右端点rrr,我们都处理左端点 1−r1-r1−r 到它的最值(下面以最大值为例),用 A[R,i]A[R, i]A[R,i] 来表示该值。
对于 A 矩阵,我们可以知道,每次查询的的就是从 A[L,L]A[L,L]A[L,L] 到 A[R,R]A[R,R]A[R,R] 的子矩阵。
考虑如何去维护这个矩阵?
这里引入一个经典问题—线段树维护历史信息和
我们对于第 i 行,知道了 A[i][1]...A[i][i]A[i][1] ... A[i][i]A[i][1]...A[i][i] ,那么对于 A[i+1]A[i + 1]A[i+1] 的这一行,只会改变 a[i+1]a[i +1]a[i+1] 为最值的那个区间,即从上一个比 a[i+1]a[i+1]a[i+1] 大的那个元素后一个开始,到 i+1i + 1i+1 ,这一段区间都是的值都是 a[i+1]a[i +1]a[i+1]。这样对每个 A[i]A[i]A[i] 可以用一棵线段树来维护,而上一个大于它的可以用单调栈来维护。

由于这道题可以离线,我们可以用一棵线段树,采用树状数组类似的方式来维护每一个A[][j]A[][j]A[][j],在 A[i][j]A[i][j]A[i][j] 第一次出现的时候,给后面每一行这个位置都加上 A[i][j]A[i][j]A[i][j] ,然后在被替换的时候,后面每一行都减去 A[i][j]A[i][j]A[i][j] ,这样的话可以采用在第一次出现的第 iii 行加上 (n+1−i)∗A[i][j](n+1-i) * A[i][j](n+1−i)∗A[i][j],被替换的第 kkk行减去 (n−k+1)∗a[k−1][j](n-k+1)*a[k-1][j](n−k+1)∗a[k−1][j] ,然后两者作差一下就是在第 i 行减去 i∗A[i][j]i*A[i][j]i∗A[i][j] ,第 k 行加上 k∗A[i][j]k *A[i][j]k∗A[i][j],这样就的更新就是 O(n)O(n)O(n) 次的。

本来这道题还要维护 tag,但是可以发现加入新的值的时候,一定会先删除掉前面的点。但是覆盖的时候还是需要tag,这里可以采用一种比较巧妙的方法,直接记录这个区间对应叶子节点的值(如果都一样的话),这样的话,就可以直接通过这个记录的值来达到 tag 的效果。

对于强制在线的情况,可以采用可持久化线段树的方式,更新是 O(n)O(n)O(n) 级别的,所以最多新建 O(nlog2n)O(n log_2n)O(nlog2​n) 个点。复杂度是可以接受的。

#include<bits/stdc++.h>
#define For(aa, bb, cc) for(int aa = (bb); aa <= (int)(cc); ++aa)
#define mk make_pair
using namespace std;
using Pair = pair<int, int>;
typedef long long LL;
const int maxn = 2e5 + 10;
constexpr int mod = 1e9 + 7;
int n, m;
int a[maxn];
vector<Pair> G[maxn];
int stmax[maxn], topa, stmin[maxn], topi;
LL ans[maxn];LL qpow(LL x, LL y = mod - 2){LL res = 1;while(y){if(y & 1) res = res * x % mod;x = x * x % mod;y >>= 1;}return res;
}void fadd(LL &x, LL y){x += y;if(x >= mod) x -= mod;
}#define lr (node << 1)
#define rr (node << 1 | 1)
#define mid ((l + r) >> 1)LL sum[maxn << 3], tr[maxn << 3];
LL point[maxn << 3], pointid[maxn << 3];
//sum: history sum, tr: now val; only cover the intervalvoid update(int node, int l, int r, int L, int R, int val, int id){fadd(sum[node], mod - 1ll * (R - L + 1) * val % mod * id % mod);fadd(tr[node], 1ll * (R - L + 1) * val % mod);//cout<<node<<" "<<l<<" "<<r<<" "<<val<<" "<<id<<" ";//cout<<sum[node]<<" "<<tr[node]<<endl;if(L <= l && r <= R){fadd(point[node], val);fadd(pointid[node], mod - 1ll * val * id % mod);//cout<<l<<" "<<r<<" "<<point[node]<<" "<<pointid[node]<<endl;return ;}if(R <= mid) return update(lr, l, mid, L, R, val, id);else if(L > mid) return update(rr, mid + 1, r, L, R, val, id);update(lr, l, mid, L, mid, val, id);update(rr, mid + 1, r, mid + 1, R, val, id);
}LL query(int node, int l, int r, int L, int R, int id){if(L <= l && r <= R) return (1ll * id * tr[node] + sum[node]) % mod;LL ans = 1ll * (point[node] * id % mod + pointid[node]) * (R - L + 1) % mod;if(R <= mid) ans += query(lr, l, mid, L, R, id);else if(L > mid) ans += query(rr, mid + 1, r, L, R, id);else return ans += query(lr, l, mid, L, mid, id) + query(rr, mid + 1, r, mid + 1, R, id);return ans % mod;
}#undef lr
#undef rr
#undef midvoid solve(){topa = topi = 0;For(i, 1, n){while(topa && a[stmax[topa]] <= a[i]){update(1, 1, n, stmax[topa - 1] + 1, stmax[topa], mod - a[stmax[topa]], i);--topa;}while(topi && a[stmin[topi]] >= a[i]){update(1, 1, n, stmin[topi - 1] + 1, stmin[topi], mod - a[stmin[topi]], i);--topi;}/*printf("stmax: ");For(j,1,topa) printf("%d ", stmax[j]);puts("");printf("stmin: ");For(j,1,topi) printf("%d ", stmin[j]);puts("");*/update(1, 1, n, stmax[topa] + 1, i, a[i], i);stmax[++topa] = i;update(1, 1, n, stmin[topi] + 1, i, a[i], i);stmin[++topi] = i;for(auto u: G[i]){int l = u.first, r = i, id = u.second;ans[id] = query(1, 1, n, l, r, i + 1) % mod;//printf("ans: %lld\n",ans[id]);ans[id] = ((mod + 1) >> 1ll) * ans[id] % mod * qpow(1ll * (r - l + 1) * (r - l + 2) / 2 % mod) % mod;}}
}int main(){#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifint _;scanf("%d", &_);while(_--){scanf("%d%d", &n ,&m);For(i, 1, n) scanf("%d", &a[i]);For(i, 1, n) G[i].clear();For(i, 1, n << 2) sum[i] = tr[i] = point[i] = pointid[i] = 0;For(i, 1, m){int x, y;scanf("%d%d", &x, &y);G[y].push_back(mk(x, i));}solve();For(i, 1, m) printf("%lld\n", ans[i]);}return 0;
}

2021HDU多校第四场5-Didn‘t I Say to Make My Abilities Average in the Next Life?!相关推荐

  1. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  2. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

  3. 牛客多校第四场【B-Basic Gcd Problem】

    牛客多校第四场[B-Basic Gcd Problem] 题目链接:https://ac.nowcoder.com/acm/contest/5669/B 思路:先要理解公式,多看几个数据基本就会有点想 ...

  4. 2022 年牛客多校第四场补题记录

    A Task Computing 题意:给定长度为 nnn 的序列 {(wi,pi)}\{(w_i,p_i)\}{(wi​,pi​)},从中选出 mmm 项并重新排列得到子序列 {a1,a2,⋯,am ...

  5. hdu2852(2009多校第四场) 树状数组求区间第k大的数 两种方法

    二分查找n*logn*logn 比较容易理解 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm& ...

  6. hdu2846(2009多校第四场) 字典树

    明明就是个简单的字典树,我不过就是想复习一下尼玛被自己坑死了T^T 把字符串分解那儿写错了,检查了半天没找到错误,然后以为被卡数组内存,难过的学习字典树的指针写法.. 发现还是不对,大半夜突然看到自己 ...

  7. hdu 4639 2013多校第四场 hehe Fibonacci 数列,组合计数,字符串处理

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4639 题目思路: 首先我们取出所有he这样的东西,考察连续的k个"he"串,通过找 ...

  8. 杭电多校第四场-H- K-th Closest Distance

    题目描述 You have an array: a1, a2, , an and you must answer for some queries. For each query, you are ...

  9. 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)

    题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...

最新文章

  1. django NoReverseMatch 错误问题
  2. 80端口攻击_内网端口转发工具的使用总结
  3. 跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)
  4. 调用gserverdkey dll的飞鸽传书2012
  5. 支持后悔药的etcdui
  6. (8)Verilog include 头文件使用路径(FPGA不积跬步101)
  7. php删除记录图片吗,php 删除记录同时删除图片文件的实现代码_PHP教程
  8. 谷歌披露利用 Windows 和安卓双平台的高阶攻击活动
  9. open cv+C++错误及经验总结(十四)
  10. 关于GitHub如何转为中文问题——Google举例
  11. 装完windows后发现C盘空间变小原因
  12. 三次样条曲线 python实现
  13. 激活windows转到电脑设置的水印怎么消失
  14. A2F-轻量级SISR网络 | Lightweight Single-Image Super-Resolution Network with Attentive Auxiliary Feature
  15. Wireshark的基本使用
  16. 基于多种分类方式的新闻文本种类预测[2021论文附代码]
  17. python语言实验指导答案_Python实验指导书
  18. 常见web安全隐患及解决方案
  19. dreamweaver html语言,Dreamweaver网页设计与制作(HTML+CSS+JavaScript)
  20. Elasticsearch基本操作:索引、文档、搜索

热门文章

  1. Flink的Source端和Sink端大全
  2. 便携式航电实时系统测试平台工作台设计
  3. matlab中怎么归一化频率,浅谈频率归一化问题
  4. 大学计算机D(VB.NET)
  5. 《Reading Wikipedia to Answer Open-Domain Questions》浅析
  6. 计算机二级c语言程序题怎么评分,计算机二级编程题怎么给分
  7. 练习-Java多路分支之月份天数计算
  8. 带你走出计算机安全防范的六个误区
  9. comma是什么键(trailing comma是什么意思)
  10. win7虚拟机上安装visual studio2017社区版的相关问题以及解决办法