2021HDU多校第四场5-Didn‘t I Say to Make My Abilities Average in the Next Life?!
题目链接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(nlog2n) 个点。复杂度是可以接受的。
#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?!相关推荐
- 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...
- 2018 HDU多校第四场赛后补题
2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...
- 牛客多校第四场【B-Basic Gcd Problem】
牛客多校第四场[B-Basic Gcd Problem] 题目链接:https://ac.nowcoder.com/acm/contest/5669/B 思路:先要理解公式,多看几个数据基本就会有点想 ...
- 2022 年牛客多校第四场补题记录
A Task Computing 题意:给定长度为 nnn 的序列 {(wi,pi)}\{(w_i,p_i)\}{(wi,pi)},从中选出 mmm 项并重新排列得到子序列 {a1,a2,⋯,am ...
- hdu2852(2009多校第四场) 树状数组求区间第k大的数 两种方法
二分查找n*logn*logn 比较容易理解 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm& ...
- hdu2846(2009多校第四场) 字典树
明明就是个简单的字典树,我不过就是想复习一下尼玛被自己坑死了T^T 把字符串分解那儿写错了,检查了半天没找到错误,然后以为被卡数组内存,难过的学习字典树的指针写法.. 发现还是不对,大半夜突然看到自己 ...
- hdu 4639 2013多校第四场 hehe Fibonacci 数列,组合计数,字符串处理
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4639 题目思路: 首先我们取出所有he这样的东西,考察连续的k个"he"串,通过找 ...
- 杭电多校第四场-H- K-th Closest Distance
题目描述 You have an array: a1, a2, , an and you must answer for some queries. For each query, you are ...
- 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)
题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...
最新文章
- django NoReverseMatch 错误问题
- 80端口攻击_内网端口转发工具的使用总结
- 跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)
- 调用gserverdkey dll的飞鸽传书2012
- 支持后悔药的etcdui
- (8)Verilog include 头文件使用路径(FPGA不积跬步101)
- php删除记录图片吗,php 删除记录同时删除图片文件的实现代码_PHP教程
- 谷歌披露利用 Windows 和安卓双平台的高阶攻击活动
- open cv+C++错误及经验总结(十四)
- 关于GitHub如何转为中文问题——Google举例
- 装完windows后发现C盘空间变小原因
- 三次样条曲线 python实现
- 激活windows转到电脑设置的水印怎么消失
- A2F-轻量级SISR网络 | Lightweight Single-Image Super-Resolution Network with Attentive Auxiliary Feature
- Wireshark的基本使用
- 基于多种分类方式的新闻文本种类预测[2021论文附代码]
- python语言实验指导答案_Python实验指导书
- 常见web安全隐患及解决方案
- dreamweaver html语言,Dreamweaver网页设计与制作(HTML+CSS+JavaScript)
- Elasticsearch基本操作:索引、文档、搜索
热门文章
- Flink的Source端和Sink端大全
- 便携式航电实时系统测试平台工作台设计
- matlab中怎么归一化频率,浅谈频率归一化问题
- 大学计算机D(VB.NET)
- 《Reading Wikipedia to Answer Open-Domain Questions》浅析
- 计算机二级c语言程序题怎么评分,计算机二级编程题怎么给分
- 练习-Java多路分支之月份天数计算
- 带你走出计算机安全防范的六个误区
- comma是什么键(trailing comma是什么意思)
- win7虚拟机上安装visual studio2017社区版的相关问题以及解决办法