题解 P3246 【[HNOI2016]序列】
很久之前做过这道题,但是跑得贼慢,现在用了可以被卡成 n m 的笛卡尔树做法,发现跑得贼快【雾
noteskey
介绍一种复杂度错误然鹅在随机数据下跑得贼快的算法: 笛卡尔树
方法就是 \(O~ n\) 构造一个笛卡尔树,然后同在线做法一样,就是每个点处理出 \(fr[i],fl[i]\) 表示以 i 为终止的前缀贡献和后缀贡献,并用 \(gr[i],gl[i]\) 表示其前/后缀和
然后每次笛卡尔树找到区间最小值的位置,然后这个点会把整个区间分成两份,这样的话我们只要处理两份区间内的答案就好了
对于两份区间我们用 \(fl~ fr~ gl~ gr\) 四个数组就可以处理出分别的贡献了
code
这份代码在洛咕 4 是怎么也跑不进 150 ms 的
//by Judge
#include<cstdio>
#include<cstring>
#include<iostream>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define ll long long
using namespace std;
const int M=1e5+3;
typedef int arr[M];
typedef ll ARR[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(ll x,char chr='\n'){
if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,m,rt,top; arr a,s,lc,rc,pre,suf; ARR fl,fr,gl,gr;
inline int query(int l,int r){ //找到这个区间内的最小值位置
for(Rg int x=rt;;x=x>r?lc[x]:rc[x])
if(l<=x&&x<=r) return x;
}
int main(){ n=read(),m=read(),a[0]=a[n+1]=2e9;
fp(i,1,n){ a[i]=read();
while(top&&a[s[top]]>=a[i]) lc[i]=s[top--];
rc[s[top]]=i,s[++top]=i;
} rt=s[1],top=0;
fp(i,1,n){
while(top&&a[s[top]]>a[i]) suf[s[top--]]=i;
pre[i]=s[top],s[++top]=i;
}
while(top) pre[s[top]]=s[top-1],suf[s[top--]]=n+1;
fp(i,1,n) fr[i]=fr[pre[i]]+1ll*a[i]*(i-pre[i]),gr[i]=gr[i-1]+fr[i];
fd(i,n,1) fl[i]=fl[suf[i]]+1ll*a[i]*(suf[i]-i),gl[i]=gl[i+1]+fl[i];
fp(i,1,m){ Rg int l=read(),r=read(),p=query(l,r); //和在线时一样的思路
print(1ll*(p-l+1)*(r-p+1)*a[p]+gr[r]-gr[p]-fr[p]*(r-p)+gl[l]-gl[p]-1ll*fl[p]*(p-l));
} return Ot(),0;
}
题解 P3246 【[HNOI2016]序列】的更多相关文章
- 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)
题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
- 【题解】HNOI2016序列
也想了有半天,没有做出来……实际上做法确实也是十分精妙的.这里推荐一个blog,个人认为这位博主讲得挺好了:Sengxian's Blog; 感觉启示是:首先要加强对莫队算法 & ST表的熟练 ...
- 洛谷P3246 [HNOI2016]序列
传送门 题解 //minamoto #include<iostream> #include<cstdio> #define ll long long using namespa ...
- 洛谷 P3246 - [HNOI2016]序列(单调栈+前缀和)
题面传送门 这道题为什么我就没想出来呢/kk 对于每组询问 \([l,r]\),我们首先求出区间 \([l,r]\) 中最小值的位置 \(x\),这个可以用 ST 表实现 \(\mathcal O(n ...
- 洛谷P3246 [HNOI2016]序列 [莫队]
传送门 思路 看到可离线.无修改.区间询问,相信一定可以想到莫队. 然而,莫队怎么转移是个大问题. 考虑\([l,r]\rightarrow[l,r+1]\)时答案会怎样变化?(左端点变化时同理) \ ...
- 题解-[HNOI2016]序列
题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...
- 【LG3246】[HNOI2016]序列
[LG3246][HNOI2016]序列 题面 洛谷 题解 60pts 对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\). 那么 ...
- [BZOJ4540][HNOI2016]序列 莫队
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...
- 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈
[BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...
随机推荐
- dedecms织梦的不同栏目调用不同banner图的方法
在做织梦站的时候我们会有不同的栏目,比如联系我们,产品中心等等,banner也不一样,方法如下: 我们可以使用织梦的顶级栏目ID标签,把图片命名成顶级栏目typeid ,代码如下: <img s ...
- jmeter学习记录--10--二次开发环境搭建
JMeter源码集成到Eclipse.JMeter二次开发(1)-eclipse环境配置及源码编译 ,根据此文章记录将jmeter源码集成到myecplise 第一步:下载jmeter源码http:/ ...
- easyui判断下拉列表
{field:'state',title:'状态',width:100, formatter : function(value, row, index){ if (value == 0) { retu ...
- HNOI2018寻宝游戏
https://www.luogu.org/problemnew/show/P4424 题解 我们首先按位考虑. 如果有一位最终的结果为1,那么我们可以把树的序列看成一个二进制数,先出现的在底位,后出 ...
- 洛谷P5155 [USACO18DEC]Balance Beam(期望,凸包)
你以为它是一个期望dp,其实它是一个凸包哒! 设平衡木长度为\(L\),把向右走平衡木那个式子写一下: \[dp[i]=\frac{dp[i+1]+dp[i-1]}{2}\] 然后会发现这是一个等差数 ...
- Java EE Expression Language
什么是EL? 形如这样(立即执行的): ${sessionScope.cart.total} 或者这样(延迟执行的): #{customer.name} 的表达式语言(Expression Langu ...
- sed命令(二)
转自:https://www.cnblogs.com/maxincai/p/5146338.html sed命令用法 sed是一种流编辑器,它是文本处理中非常有用的工具,能够完美的配合正则表达式使用, ...
- day20面向对象三大特性 , 类嵌套
#!/usr/bin/env python# -*- coding:utf-8 -*- # 1.简述面向对象三大特性并用代码表示."""封装:class Account: ...
- [Luogu P1119]灾后重建
这是一道考Floyd本质的题. 回忆一下Floyd的原理,三层循环,最外层循环枚举的是中转点,也就是用两点到中转点距离之和来更新最短路.然后来看下题目,重建时间是按照从小到大排序的,也就是说,当第i个 ...
- (Python3) 求中位数 代码
def zhongweishu(a): new=sorted(a) if len(a)%2==0: s=(new[int(len(a)/2-1)]+new[int(len(a)/2)])/2 else ...