bzoj 4540: [Hnoi2016]序列
Description
给定长度为n的序列:a1,a2,…,an,记为a[1:n]。类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-
1,ar。若1≤l≤s≤t≤r≤n,则称a[s:t]是a[l:r]的子序列。现在有q个询问,每个询问给定两个数l和r,1≤l≤r
≤n,求a[l:r]的不同子序列的最小值之和。例如,给定序列5,2,4,1,3,询问给定的两个数为1和3,那么a[1:3]有
6个子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],这6个子序列的最小值之和为5+2+4+2+2+2=17。
Solution
我们设 \(f[i][j]\) 表示区间 \([i,j]\) 的最小值,那么答案就是 \(\sum\sum f[i][j]\)
我们把 \(f[i][j]\) 画成一个矩形,例如:
7
5 4
3 3 3
3 3 2 2
那么如果我们枚举了一个右端点 \(j\),那么就相当于是求第 \(j\) 行的和
从这一行到下一行实际上就是先平移下来,然后再把新加进来的元素做一次区间覆盖
设 \(L[i]\) 为 \(i\) 作为最小值能够往左延伸到的最远的位置,那么就是对 \([L[i],i]\) 做一个区间覆盖,并且我们还要维护一个区间和,由于还枚举了右端点,所以还要维护历史信息
那么线段树分别维护 \(s,v,l\) 表示,历史的区间和的总和,当前的区间和,区间长度
并且维护四个标记 \(a,b,c,d\),表示标记生效后, \(v=v*a+b*l\),\(s=s+v*c+d*l\)
标记的合并有一些讨论,见代码
扫描线+线段树维护这个东西即可
#include<bits/stdc++.h>
#define ls (o<<1)
#define rs (o<<1|1)
using namespace std;
typedef long long ll;
const int N=1e5+10;
inline int gi(){
register int str=0;register char ch=getchar();bool f=0;
while(ch>'9' || ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
return f?-str:str;
}
int n,a[N],Q,cnt=0,L[N],st[N],top=0;ll ans[N];
struct Qu{int x,l,r,k,id;}q[N*2];
inline bool comp(const Qu &i,const Qu &j){return i.x<j.x;}
struct tag{
ll a,b,c,d;
tag(){a=1;b=0;c=0;d=0;}
tag(ll _a,ll _b,ll _c,ll _d){a=_a;b=_b;c=_c;d=_d;}
tag operator +(tag &p){return tag(a*p.a,b*p.a+p.b,a*p.c+c,d+p.d+b*p.c);}
};
struct node{
ll v,s,l;tag t;
node(){v=s=l=0;t=tag();}
node(ll _v,ll _s,ll _l,tag _t){v=_v;s=_s;l=_l;t=_t;}
node operator +(const node &p){return node(v+p.v,s+p.s,l+p.l,tag());}
inline void add(tag x){s+=v*x.c+l*x.d;v=x.a*v+x.b*l;t=t+x;}
}tr[N*4];
inline void build(int l,int r,int o){
if(l==r){tr[o]=node();tr[o].l=1;return ;}
int mid=(l+r)>>1;
build(l,mid,ls);build(mid+1,r,rs);
tr[o]=tr[ls]+tr[rs];
}
inline void pushdown(int o){
tag t=tr[o].t;
if(t.a==1 && !t.b && !t.c && !t.d)return ;
tr[o].t=tag();tr[ls].add(t);tr[rs].add(t);
}
inline void Modify(int l,int r,int o,int sa,int se,tag t){
if(sa<=l && r<=se){tr[o].add(t);return ;}
pushdown(o);
int mid=(l+r)>>1;
if(se<=mid)Modify(l,mid,ls,sa,se,t);
else if(sa>mid)Modify(mid+1,r,rs,sa,se,t);
else Modify(l,mid,ls,sa,mid,t),Modify(mid+1,r,rs,mid+1,se,t);
tr[o]=tr[ls]+tr[rs];
}
inline node qry(int l,int r,int o,int sa,int se){
if(sa<=l && r<=se)return tr[o];
pushdown(o);
int mid=(l+r)>>1;node ret;
if(se<=mid)ret=qry(l,mid,ls,sa,se);
else if(sa>mid)ret=qry(mid+1,r,rs,sa,se);
else ret=qry(l,mid,ls,sa,mid)+qry(mid+1,r,rs,mid+1,se);
tr[o]=tr[ls]+tr[rs];
return ret;
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>Q;
for(int i=1;i<=n;i++)a[i]=gi();
for(int i=1;i<=n;i++){
while(top && a[i]<a[st[top]])top--;
L[i]=st[top]+1;st[++top]=i;
}
int x,y;
for(int i=1;i<=Q;i++){
x=gi();y=gi();
q[++cnt]=(Qu){y,x,y,1,i};
}
sort(q+1,q+cnt+1,comp);
build(1,n,1);
for(int i=1,j=1;i<=n;i++){
Modify(1,n,1,L[i],i,tag(0,a[i],0,0));tr[1].add(tag(1,0,1,0));
while(j<=cnt && q[j].x<i)j++;
for(;j<=cnt && q[j].x==i;j++)
ans[q[j].id]+=qry(1,n,1,q[j].l,q[j].r).s;
}
for(int i=1;i<=Q;i++)printf("%lld\n",ans[i]);
return 0;
}
bzoj 4540: [Hnoi2016]序列的更多相关文章
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...
- BZOJ 4540 [Hnoi2016]序列 | 莫队 详细题解
传送门 BZOJ 4540 题解 --怎么说呢--本来想写线段树+矩阵乘法的-- --但是嘛--yali的机房太热了--困--写不出来-- 于是弃疗,写起了莫队.(但是我连莫队都想不出来!) 首先用单 ...
- BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)
BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...
- bzoj 4540: [Hnoi2016]序列 莫队
题目: 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称a[s:t]是a ...
- BZOJ 4540 [Hnoi2016]序列 (单调栈 + ST表 + 莫队算法)
题目链接 BZOJ4540 考虑莫队算法. 这题难在$[l, r]$到$[l, r+1]$的转移. 根据莫队算法的原理,这个时候答案应该加上 $cal(l, r+1) + cal(l+1, r+1) ...
- bzoj 4540: [Hnoi2016]序列【单调栈+线段树】
强烈安利:http://blog.csdn.net/qq_34637390/article/details/51313126 这篇讲标记讲的非常好,这个标记非常神奇-- 首先last表示扫描到last ...
- 4540: [Hnoi2016]序列
4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ...
- [BZOJ4540][HNOI2016]序列 莫队
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...
- [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1567 Solved: 718[Submit][Status] ...
随机推荐
- 三张图片看懂ZKEACMS的设计思想
前言 如果你还不知道ZKEACMS,不妨先了解一下. ASP.NET MVC 开源建站系统 ZKEACMS 推荐,从此网站“拼”起来 官方地址:http://www.zkea.net/zkeacms ...
- java简答题
1.什么是java的平台无关性? Java源文件被编译成字节码的形式,无论在什么系统环境下,只要有java虚拟机就能运行这个字节码文件.也就是一处编写,处处运行.这就是java的跨平台性. 2.在一台 ...
- 使用adb工具调试出现error:device offline
使用adb工具调试设备的时候会出现error:device offline,网上找了很多办法,最后终于解决了. 如果你也遇到这样的问题,先试试简单的办法,不行的话,试试这个..<.< ad ...
- linux命令之文件系统管理命令(下)
1.mount:挂载文件系统 该命令可以将指定的文件系统挂载到指定目录(挂载点),在linux中必须先挂载所有的设备,才能够访问,挂载的目录必须事先存在并且最好为空. 参数 说明 -t(常用) 指定挂 ...
- python list的append()和extend()方法
引用自:https://www.cnblogs.com/subic/p/6553187.html
- better-scroll在vue中的应用
在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 微信 —> 钱包—>滴滴出行”体验效果. 什么是 better-scrol ...
- jmeter性能测试指标
1.jp@gc - Actiive Threads Over Time:不同时间的活动用户数量展示(图表) 当前的时间间隔是1毫秒,在setting中可以设置时间间隔以及其他的参数 2.jp@gc - ...
- dbproxy-id生成器
id生成器使用的是snowflake, 需要执行 snowflake_init(region_id, worker_id); 而region_id和worker_id是在配置文件中配置的 networ ...
- six
团队序号:6组 团队名称:拯救地球小分队 团队项目的码云地址:https://gitee.com/lwj5950/seflash 此次博客撰写人姓名:刘威骏 学号:2017*****7168 团队中的 ...
- LOJ565. 「LibreOJ Round #10」mathematican 的二进制(NTT)
题目链接 https://loj.ac/problem/565 题解 首先,若进行所有操作之后成功执行的操作数为 \(m\),最终得到的数为 \(w\),那么发生改变的二进制位的数量之和(即代价之和) ...