BZOJ 4540 [Hnoi2016]序列
来源:互联网 发布:linux 下载php源码 编辑:程序博客网 时间:2024/06/14 07:20
线段树+矩阵
我来发一篇博客证明我还活着
题目要求的区间所有子区间的最小值之和不太容易合并,因此直接上数据结构不好做。
考虑离线做法。把所有询问右端点排序。
从左到右扫描整个序列,扫描到
如何随着
然后大概卡了一个中午的常数吧。
#include<cstdio>#include<vector>#include<cstring>#define N 100005using namespace std;int read(){ int r = 0, p = 0; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) c == '-' ? p = 1 : 0; for(; c >='0' && c <='9'; r = r*10+c-'0', c = getchar()); return p?-r:r;}namespace runzhe2000{ typedef long long ll; const int INF = 1<<30; int n, q, a[N], sta[N], stacnt, nocnt; ll ans[N]; struct que{int id, l; que *next;}node[N], *last[N]; struct matrix { ll a[3][3]; matrix(){memset(a,0,sizeof(a));} matrix operator * (matrix &that) { matrix r; for(int i = 0; i < 3; i++) { ll *rai = r.a[i], *ai = a[i]; for(int j = 0; j < 3; j++) for(int k = 0; k < 3; k++) rai[j] += ai[k]*that.a[k][j]; } return r; } }I, mat_v, mat_sum; struct seg { matrix val, tag; int need; }t[N*4]; void pushdown(int x) { if(!t[x].need)return; t[x].need = 0; seg *ls = &t[x<<1], *rs = &t[x<<1|1]; ls->val = ls->val * t[x].tag; ls->tag = ls->tag * t[x].tag; rs->val = rs->val * t[x].tag; rs->tag = rs->tag * t[x].tag; ls->need = rs->need = 1; t[x].tag = I; } void pushup(int x) { ll *a0 = t[x].val.a[0], *a0l = t[x<<1].val.a[0], *a0r = t[x<<1|1].val.a[0]; for(int i = 0; i < 3; i++) a0[i] = a0l[i] + a0r[i]; } void build(int x, int l, int r) { t[x].val.a[0][2] = r-l+1; t[x].tag = I; t[x].need = 0; if(l == r) return; int mid = (l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); } void modi(int x, int l, int r, int ql, int qr, matrix &val) { if(ql <= l && r <= qr) { t[x].need = 1; t[x].tag = t[x].tag * val; t[x].val = t[x].val * val; return; } pushdown(x); int mid = (l+r)>>1; if(ql <= mid) modi(x<<1,l,mid,ql,qr,val); if(mid < qr) modi(x<<1|1,mid+1,r,ql,qr,val); pushup(x); } ll query(int x, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return t[x].val.a[0][0]; int mid = (l+r)>>1; ll ret = 0; pushdown(x); if(ql <= mid) ret += query(x<<1,l,mid,ql,qr); if(mid < qr) ret += query(x<<1|1,mid+1,r,ql,qr); return ret; } void main() { n = read(), q = read(); for(int i = 1; i <= n; i++) a[i] = read(); for(int i = 0; i < 3; i++) I.a[i][i] = mat_sum.a[i][i] = 1; mat_sum.a[1][0] = 1; mat_v.a[0][0] = mat_v.a[2][2] = 1; build(1,1,n); for(int i = 1; i <= q; i++) { int l = read(), r = read(); node[++nocnt] = (que){i,l,last[r]}; last[r] = &node[nocnt]; } a[0] = -INF; for(int i = 1; i <= n; i++) { for(; a[sta[stacnt]] >= a[i]; stacnt--); mat_v.a[2][1] = a[i]; modi(1,1,n,sta[stacnt]+1,i,mat_v); modi(1,1,n,1,i,mat_sum); sta[++stacnt] = i; for(que *j = last[i]; j; j = j->next) { ans[j->id] = query(1,1,n,j->l,i); } } for(int i = 1; i <= q; i++) printf("%lld\n",ans[i]); }}int main(){ runzhe2000::main();}
阅读全文
0 0
- bzoj 4540: [Hnoi2016]序列
- BZOJ 4540 [Hnoi2016]序列
- [莫队 单调栈] BZOJ 4540 [Hnoi2016]序列
- bzoj 4540: [Hnoi2016]序列 莫队算法
- BZOJ 4540: [Hnoi2016]序列 莫队算法
- BZOJ 4542([Hnoi2016]序列-莫队)
- bzoj 4540: [Hnoi2016]序列 莫队算法+rmq
- [bzoj 4540] [Hnoi2016]序列:离线,线段树,矩阵乘法
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- bzoj 4540: [Hnoi2016]序列 (莫队+ST表+单调栈|线段树)
- 【HNOI2016】序列
- 4540: [Hnoi2016]序列|莫队+ST表
- BZOJ 4538: [Hnoi2016]网络
- BZOJ 4539: [Hnoi2016]树
- BZOJ 4542: [Hnoi2016]大数
- BZOJ 4537: [Hnoi2016]最小公倍数
- on()方法的多种用法。
- jQuery tmpl详解
- Dubbo+Zookeeper视频
- 由浅入深理解java集合(一)
- 安卓在代码中设置TextView的drawableLeft、drawableRight、drawableTop、drawableBottom
- BZOJ 4540 [Hnoi2016]序列
- 抽丝剥茧看路由_angular1.X---1
- Java中什么是字符文件,什么是字节文件?
- 回文链表
- Linux/Centos 在用搜索命令locate时 command not found 问题
- POI相关
- MySQL大表删除解决方案
- Preconditions优雅的检验参数(Guava)
- 由浅入深理解java集合(二)