当前位置: 首页 > news >正文

洛谷P3722 [AHOI2017/HNOI2017] 影魔

0x1f 关于思路

妙妙妙!

可以发现,暴力的枚举点对可以在 \(O(n^2)\) 的复杂度下解决问题。

似乎不能优化了。

对于这样的困境,一种思路是计算每个点的贡献,枚举的复杂度就降下来了。

考虑对题意进行转化:求出每个点左边第一个比他大的数 \(L_i\),右边同理 \(R_i\)

这样答案的贡献可以转换成三部分。

  1. \(R_i\)\([L_i,i-1]\) 的区间产生 \(p_2\) 的贡献。
  2. \(L_i\)\([i+1,R_i]\) 的区间产生 \(p_2\) 的贡献。
  3. \(L_i\)\(R_i\) 产生 \(p_1\) 的贡献。

我们可以离线地按询问左端点排序询问,每到一个点,如果是右端点,那就线段树区间查询。

每到一个点 \(R_i\),区间加上贡献 \(1\)\(L_i\) 加上贡献 \(2\)

至于贡献 \(3\),我们慎重考虑,因为线段树区间查询,所以如果区间内一个点的 \(R_i\) 在区间外右侧,那就不应该统计。

所以贡献 \(3\) 应该在右端点时再加上。

0x2f 关于代码

\(\huge \mathscr{Code}\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5+100;
int n,m,p1,p2,val[N],L[N],R[N],ans[N];
struct node{int l,r,pos,id,ki;friend bool operator<(node a,node b) {return a.pos<b.pos;}
}Q[N<<1];
class G{public:struct GG{int ans,tag;}T[N<<2];inline void pushup(int u){T[u].ans = T[u*2].ans + T[u*2+1].ans;}inline void pushdown(int u,int l,int r){if(T[u].tag){int mid = (l+r)>>1;T[u*2].ans += (mid-l+1)*T[u].tag;T[u*2+1].ans += (r-mid)*T[u].tag;T[u*2].tag += T[u].tag;T[u*2+1].tag += T[u].tag;T[u].tag = 0; }}void update(int u,int l,int r,int ql,int qr,int v){if(ql<=l && r<=qr){T[u].ans += (r-l+1)*v;T[u].tag += v;return;}pushdown(u,l,r);int mid = (l+r)>>1;if(ql<=mid) update(u*2,l,mid,ql,qr,v);if(qr>mid) update(u*2+1,mid+1,r,ql,qr,v);pushup(u);}int query(int u,int l,int r,int ql,int qr){if(ql<=l && r<=qr) return T[u].ans;pushdown(u,l,r);int mid = (l+r)>>1,ans = 0;if(ql<=mid) ans += query(u*2,l,mid,ql,qr);if(qr>mid) ans += query(u*2+1,mid+1,r,ql,qr);return ans;}
}S;
int stk[N],top;
struct num{int l,r,ki;
};
vector<num> event[N];
signed main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>m>>p1>>p2;for(int i=1;i<=n;i++) cin>>val[i];val[n+1] = n+1;stk[++top] = 0;for(int i=1;i<=n+1;i++){while(top && val[stk[top]]<val[i]) R[stk[top--]] = i;L[i] = stk[top];stk[++top] = i;}for(int i=1;i<=n;i++){if(L[i]>=1 && R[i]<=n) event[R[i]].push_back(num{L[i],L[i],p1});if(L[i]+1<i && R[i]<=n) event[R[i]].push_back(num{L[i]+1,i-1,p2});if(L[i]>=1 && R[i]>i+1) event[L[i]].push_back(num{i+1,R[i]-1,p2});}for(int i=1;i<=m;i++){int l,r;cin>>l>>r;ans[i] += (r-l)*p1;Q[i] = node{l,r,l-1,i,-1},Q[i+m] = node{l,r,r,i,1};}sort(Q+1,Q+2*m+1);int pos = 1;while(pos<=m*2 && !Q[pos].pos) pos++;for(int i=1;i<=n;i++){for(num e:event[i]){S.update(1,1,n,e.l,e.r,e.ki);}while(pos<=m*2 && Q[pos].pos==i){ans[Q[pos].id] += Q[pos].ki*S.query(1,1,n,Q[pos].l,Q[pos].r);pos++;}}for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';return 0;
}
http://www.sczhlp.com/news/9030/

相关文章:

  • 4.2 数据类型内置方法--不可变类型
  • 8.2每周总结
  • 故障处理:ORA-troubleshooting not JPPD cause View is a set query block
  • 8.9每日总结
  • 基于MATLAB的Relief-F算法实现
  • inf种线段树
  • esp32等网络设备 初始化、联网、发出一个http请求全程简述
  • ES 调优帖:Gateway 批量写入性能优化实践
  • 读书笔记:为什么程序员总爱小步快跑提交事务?这个习惯可能害了你!
  • 故障处理:Oracle:EXP-00056 ORA-04063处理过程
  • Rust 你太难了! - ukyo-
  • OpenGauss v6.0.2集中式1主2从部署指南
  • Introducing Shoka
  • day01-智能体与Coze初识
  • 8。9
  • JS 原⽣⽀持⾃定义事件
  • 完整教程:Redux与React-环境准备(React快速上手1)
  • 二叉树路径类问题
  • 多租户模型推理成本追踪方案解析
  • 【项目复盘】从0到1打造AI零售门店助手:多轮对话、动态推荐与跨行业技术迁移深度解析
  • 释放美杜莎:快速可扩展的智能合约模糊测试技术
  • uniapp-vue2导航栏全局自动下拉变色 - 详解
  • 尚硅谷Java设计模式
  • Windows 11家庭版中删除输入法
  • 数据库的意向锁
  • 语音活动检测(VAD)
  • 2025.8.10
  • 【话题讨论】AI与XR融合的未来:大模型如何重塑AR/VR/MR产业应用与开发模式 - EQ
  • Windows 与 Linux 换行符冲突问题及解决办法
  • 香橙派 RK3588 部署 DeepSeek