当前位置:网站首页>2021HNCPC-E-差分,思维
2021HNCPC-E-差分,思维
2022-07-25 15:23:00 【塔子哥来了】
题目大意:
求解每一个 f ( i ) f(i) f(i)代表 m a x ( a j , . . . , a i ) − ( j − i + 1 ) ≥ m max(a_j,...,a_i)-(j-i+1) \geq m max(aj,...,ai)−(j−i+1)≥m的 j j j的个数. j ≤ i j \leq i j≤i
n ≤ 1 e 6 n \leq 1e6 n≤1e6
思路:
关键:看到 m a x ( a j , . . . , a i ) max(a_j,...,a_i) max(aj,...,ai),想到枚举 a i a_i ai,考虑它所管辖的范围(单调栈求解).
PS:当有相同的值时,可以规定将区间贡献记在最右边的值上。
那么就转化成 ( j − i + 1 ) ≤ m a x ( a j , . . . , a i ) − m (j-i+1) \leq max(a_j,...,a_i)-m (j−i+1)≤max(aj,...,ai)−m.
然后枚举右半边,分情况讨论来区间加等差序列即可.
代码仓库:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
int a[maxn] , l[maxn] , r[maxn] , b[maxn];
int n , m;
template <typename T>
void read(T & x){
x = 0;T f = 1;char ch = getchar();while(!isdigit(ch)){
if(ch == '-') f = -1;
ch = getchar();}while (isdigit(ch)){
x = x * 10 + (ch ^ 48);ch = getchar();}x *= f;}
template <typename T>
void write(T x){
if(x < 0){
putchar('-');x = -x;}if (x > 9)write(x / 10);putchar(x % 10 + '0');}
void add (int l , int r , int s , int d){
if (l > r) return ;
int t = s + (r - l) * d;
b[l] += s;
b[l+1] += d - s;
b[r+1] -= d + t;
b[r+2] += t;
}
void solve (){
for (int i = 1 ; i <= n ; i++) b[i] = 0;
for (int i = 1 ; i <= n ; i++){
int g = a[i] - m;
if (g <= 0) continue;
int v = i - l[i] + 1;
if (v >= g){
add(i , min(i + g - 1 , r[i]) , g , -1);
}else{
int gap = g - v;
int e1 = min(i + gap , r[i]);
add(i , e1 , v , 0);
add(e1 + 1 , min(r[i] , e1 + v - 1) , v - 1 , -1);
}
}
for (int i = 1 ; i <= n ; i++) b[i] += b[i - 1];
for (int i = 1 ; i <= n ; i++) b[i] += b[i - 1];
}
int main()
{
while (~scanf("%d%d" , &n, &m)){
for (int i = 1 ; i <= n ; i++) read(a[i]);
stack<int> s;
for (int i = 1 ; i <= n ; i++){
while (s.size() && a[s.top()] <= a[i]) s.pop();
if (s.size()) l[i] = s.top() + 1;
else l[i] = 1;
s.push(i);
}
while (s.size()) s.pop();
for (int i = n ; i >= 1 ; i--){
while (s.size() && a[i] > a[s.top()]) s.pop();
if (s.size()) r[i] = s.top() - 1;
else r[i] = n;
s.push(i);
}
solve();
for (int i = 1 ; i <= n ; i++) printf("%d " , b[i]);
printf("\n");
}
return 0;
}
边栏推荐
- Once spark reported an error: failed to allocate a page (67108864 bytes), try again
- Iframe nested other website page full screen settings
- 小波变换--dwt2 与wavedec2
- Flex 布局
- wait()和sleep()的区别理解
- ML - 自然语言处理 - 关键技术
- 带你详细认识JS基础语法(建议收藏)
- 苹果内购和Apple Pay 的区别
- Spark SQL null value, Nan judgment and processing
- matlab 如何保存所有运行后的数据
猜你喜欢
随机推荐
期货在线开户是否安全?去哪家公司手续费最低?
JVM-动态字节码技术详解
谷歌云盘如何关联Google Colab
Find out what happened in the process of new
MySql的安装配置超详细教程与简单的建库建表方法
二进制补码
Is it safe to open futures online? Which company has the lowest handling charge?
matlab 优化工具 manopt 安装
记一次Spark报错:Failed to allocate a page (67108864 bytes), try again.
Submarine cable detector tss350 (I)
CGO is realy Cool!
Implementation of asynchronous FIFO
自定义注解校验API参数电话号
带你详细认识JS基础语法(建议收藏)
Spark AQE
数据系统分区设计 - 请求路由
Xcode添加mobileprovision证书文件报错:Xcode encountered an error
Application of object detection based on OpenCV and yolov3
本地缓存--Ehcache
Instance Tunnel 使用









