bzoj4262 Sum
来源:互联网 发布:js隐藏input标签 编辑:程序博客网 时间:2024/06/12 20:25
题目大意
给出一个随机数列
数据范围
解题报告
考虑离线的做法,把询问拆成
从左往右移动右端点,当移动到位置
在线段树上打标记来维护,线段上每个节点记录:
再维护以下标记:
向上合并的做法很简单:
因为修改操作其实也和下放标记的操作类似,我们只用考虑如何用一个标记去修改一个节点维护的数据和标记:
用标记
用标记
如果标记
否则:
之后就是简单的线段树操作了,不再赘述。
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int gint(){ char c; int f=1; while(c=getchar(),c<48||c>57) if(c=='-')f=-1; int x=0; for(;c>47&&c<58;c=getchar()){ x=x*10+c-48; } return x*f;}#define max_N 100005#define mod 1000000000int n,A[max_N];void init(){ int g1=1,g2=1; for(int i=1;i<=n;++i){ g1=1ll*g1*1023%mod; g2=1ll*g2*1025%mod; A[i]=g1^g2; }}struct QY{ int l,r,f,id,next; QY(int l=0,int r=0,int f=0,int id=0,int n=0):l(l),r(r),f(f),id(id),next(n){}}Q[max_N];int t,head[max_N],tot;inline void add_QY(int x,int l,int r,int f,int id){ if(!x)return; Q[++tot]=QY(l,r,f,id,head[x]),head[x]=tot;}typedef long long ll;struct data{ ll v,s; int t; }T[max_N<<2];inline data merge(const data&a,const data&b){ data res; res.v=a.v+b.v; res.t=max(a.t,b.t); res.s=a.s+b.s+a.v*(res.t-a.t)+b.v*(res.t-b.t); return res;}struct tags{ int a,tl,tr; ll s;}tag[max_N<<2];inline void modify(data&x,const tags&y,int len){ x.s+=x.v*(y.tl-x.t)+y.s*len; x.v=1ll*y.a*len; x.t=y.tr;}inline void modify(tags&x,const tags&y){ if(x.a==-1){x=y; return;} x.s+=1ll*x.a*(y.tl-x.tr)+y.s; x.a=y.a,x.tr=y.tr;}inline void putdown(int x,int l,int m,int r){ if(tag[x].a==-1)return; modify(T[x<<1],tag[x],m-l+1); modify(tag[x<<1],tag[x]); modify(T[x<<1|1],tag[x],r-m); modify(tag[x<<1|1],tag[x]); tag[x].a=-1;}#define lch x<<1,l,m#define rch x<<1|1,m+1,rvoid modify(int x,int l,int r,int ll,int rr,int a,int t){ if(ll<=l&&r<=rr){ tags y; y.a=a,y.s=0,y.tl=y.tr=t; modify(T[x],y,r-l+1); modify(tag[x],y); return; } int m=(l+r)>>1; putdown(x,l,m,r); if(ll<=m)modify(lch,ll,rr,a,t); if(rr>m) modify(rch,ll,rr,a,t); T[x]=merge(T[x<<1],T[x<<1|1]);}data query(int x,int l,int r,int ll,int rr){ if(l==ll&&r==rr)return T[x]; int m=(l+r)>>1; putdown(x,l,m,r); if(rr<=m)return query(lch,ll,rr); if(ll>m) return query(rch,ll,rr); return merge(query(lch,ll,m),query(rch,m+1,rr));}int st[max_N],top;ll ans[max_N];void Tree_init(int x,int l,int r){ T[x].v=T[x].s=T[x].t=0; tag[x].a=-1; if(l==r)return; int m=(l+r)>>1; Tree_init(x<<1,l,m); Tree_init(x<<1|1,m+1,r);}int main(){// freopen("input.txt","r",stdin); t=gint(); for(int i=1,l1,r1,l2,r2;i<=t;++i){ l1=gint(),r1=gint(),l2=gint(),r2=gint(); add_QY(l2-1,l1,r1,-1,i),add_QY(r2,l1,r1,1,i); n=max(n,max(r1,r2)); } init(); Tree_init(1,1,n); top=0; for(int i=1;i<=n;++i){ while(top&&A[st[top]]<=A[i])--top; modify(1,1,n,st[top]+1,i,A[i],i); st[++top]=i; for(int j=head[i];j;j=Q[j].next){ data tmp=query(1,1,n,Q[j].l,Q[j].r); ans[Q[j].id]+=(tmp.s+tmp.v*(i-tmp.t+1))*Q[j].f; } } Tree_init(1,1,n); top=0; for(int i=1;i<=n;++i){ while(top&&A[st[top]]>=A[i])--top; modify(1,1,n,st[top]+1,i,A[i],i); st[++top]=i; for(int j=head[i];j;j=Q[j].next){ data tmp=query(1,1,n,Q[j].l,Q[j].r); ans[Q[j].id]+=(tmp.s+tmp.v*(i-tmp.t+1))*Q[j].f*-1; } } for(int i=1;i<=t;++i){ printf("%lld\n",ans[i]); } return 0;}
- bzoj4262: Sum
- bzoj4262 Sum
- 【bzoj4262】Sum 线段树+单调队列
- Sum
- sum
- sum
- Sum
- Sum
- Sum
- sum
- Sum
- sum
- Sum
- sum
- Sum
- sum
- Sum Sum Sum
- HDU5150 Sum Sum Sum
- Linux下通过加载内核计算CPU利用率以及内存利用率
- swift中tableView的上下拉刷新<MJRefresh>
- 2017微软面试算法题回顾
- GitHub上fork项目后与作者源代码保持一致的方法
- 面向对象与C++程序设计-字符串流学习笔记
- bzoj4262 Sum
- iframe跨域
- Spring 定时任务之 @Scheduled cron表达式
- <c:forEach> 循环<a> 标签 发送其他DELETE、PUT、POST请求
- nginx 配置去掉URL中工程名
- 如何完成一个有效的面试——善用STAR法则
- 使用maven搭建hadoop环境
- c语言 sizeof详解
- Dependencies 报错之 版本号