当前位置:网站首页>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;
}
边栏推荐
- How to update JSON values in the database?
- JVM garbage collector details
- C#精挑整理知识要点10 泛型(建议收藏)
- CGO is realy Cool!
- ML - 语音 - 深度神经网络模型
- Example of password strength verification
- Tasks, micro tasks, queues and scheduling (animation shows each step of the call)
- 数据系统分区设计 - 请求路由
- Maxcompute SQL 的查询结果条数受限1W
- 带你详细认识JS基础语法(建议收藏)
猜你喜欢
随机推荐
获取键盘按下的键位对应ask码
Spark DF adds a column
How to solve the login problem after the 30 day experience period of visual stuido2019
JVM garbage collector details
The difference between Apple buy in and apple pay
HBCK fix problem
ios 面试题
Idea eye care settings
Single or multiple human posture estimation using openpose
C language function review (pass value and address [binary search], recursion [factorial, Hanoi Tower, etc.))
二进制补码
C#精挑整理知识要点10 泛型(建议收藏)
如何更新更新数据库中的json值?
Example of password strength verification
ML - 语音 - 语音处理介绍
Is it safe to open futures online? Which company has the lowest handling charge?
Remember that spark foreachpartition once led to oom
分布式原理 - 什么是分布式系统
UIDocumentInteractionController UIDocumentPickerViewController
Find out what happened in the process of new









