ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21.10.3 T4

2021-10-03 20:00:46  阅读:197  来源: 互联网

标签:int T4 mid 21.10 qry rid lz id


题意

给定一个长度为\(n\)的区间\(a_i\)与\(m\)个询问,每次询问给出\(l,r\),求

\[\sum_{i=l}^r\sum_{j=l}^r(max_{k=i}^ja_k)\times(min_{k=i}^{j}a_k) \]

\(n,m\leq10^5\)

sol

考虑分治。

对于每个区间我们只维护所有跨过了\(mid\)的区间\([i,j]\)对答案的,对于其他多于此的询问的其他区间我们继续下放处理。

对于一个区间,我们枚举右端点,根据\([l,mid]\)中每个点与右端点间\(min,max\)分别是在\([l,mid]\)或是\([mid+1,r]\)上分成四种情况,即\(min/max\)在或不在\([l,mid]\)区间内。容易发现这样的划分方式将\([l,mid]\)划分成了至多四段(可能有重),则该段答案即为四种情况之和。

对于这四种情况,我们建四棵线段树,维护区间和,支持区间加,来维护其系数。(其实显然可以树状数组,考场上脑子抽了)

具体的,我们预处理出整个大区间\([1,n]\)分治的答案,为方便下传询问,将询问打包成个\(vector\),一起下放即可。

但是这码\(T\)了(((

所以还是用树状数组吧\(QAQ\)

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define N 100005
#define M N<<3
#define lid (id<<1)
#define rid (id<<1|1)
#define mid ((l+r)>>1)
int s[N],maxx[N],minn[N],ans[N],f[M],n,m;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return x*f;
}
inline void add1(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline int add2(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
struct seg_tr{
	int lz[M],sum[M],siz[M],num[N];
	void build(int id,int l,int r){
		sum[id]=lz[id]=0;
		if(l==r) siz[id]=num[l];
		else{
			build(lid,l,mid),build(rid,mid+1,r);
			siz[id]=add2(siz[lid],siz[rid]);
		}
	}
	inline void pushdown(int id){
		lz,add1(lz[rid],lz[id]);
		add1(sum[lid],1LL*lz[id]*siz[lid]%mod);
		add1(sum[rid],1LL*lz[id]*siz[rid]%mod);
		lz[id]=0;
	}
	inline void add(int id,int l,int r,int x,int y,int z){
		if(l==x&&r==y) add1(lz[id],z),add1(sum[id],1LL*z*siz[id]%mod);
		else{
			if(lz[id]) pushdown(id);
			if(y<=mid) add(lid,l,mid,x,y,z);
			else if(x>mid) add(rid,mid+1,r,x,y,z);
			else add(lid,l,mid,x,mid,z),add(rid,mid+1,r,mid+1,y,z);
			sum[id]=add2(sum[lid],sum[rid]);
		}
	}
	inline int qry(int id,int l,int r,int x,int y){
		if(l==x&&r==y) return sum[id];
		if(lz[id]) pushdown(id);
		if(y<=mid) return qry(lid,l,mid,x,y);
		if(x>mid) return qry(rid,mid+1,r,x,y);
		return add2(qry(lid,l,mid,x,mid),qry(rid,mid+1,r,mid+1,y));
	}
}tr[5];

struct query{int l,r,id;};
vector<query >qry[M];
inline bool cmpr(query x,query y){return x.r<y.r;}
inline void solve(int id,int l,int r){
	int cnt=qry[id].size();
	if(l==r){
		f[id]=1LL*s[l]*s[l]%mod;
		for(int i=0;i<cnt;i++) add1(ans[qry[id][i].id],1LL*s[l]*s[l]%mod);
		return;
	}
	sort(qry[id].begin(),qry[id].end(),cmpr);
	int lsw=0;while(lsw<cnt&&qry[id][lsw].r<=mid) lsw++;
	maxx[mid]=minn[mid]=s[mid];
	for(int i=mid-1;i>=l;--i){
		maxx[i]=max(maxx[i+1],s[i]);
		minn[i]=min(minn[i+1],s[i]);
	}
	for(int i=l;i<=mid;i++){
		tr[0].num[i]=1;
		tr[1].num[i]=maxx[i];
		tr[2].num[i]=minn[i];
		tr[3].num[i]=1LL*maxx[i]*minn[i]%mod;
	}
	int ma,mi;
	ma=mi=s[mid+1];
	int x,y,z;x=y=z=mid+1;
	for(int i=0;i<4;i++) tr[i].build(1,l,mid);
	for(int i=mid+1;i<=r;i++){
		ma=max(ma,s[i]),mi=min(mi,s[i]);
		
		while(l<x&&minn[x-1]>=mi&&maxx[x-1]<=ma)x--;
		while(l<y&&minn[y-1]>=mi)y--;
		while(l<z&&maxx[z-1]<=ma)z--;
		
		if(x<=mid)tr[0].add(1,l,mid,x,mid,1LL*ma*mi%mod);
		if(y<x){
			tr[1].add(1,l,mid,y,x-1,mi);
			if(l<y)tr[3].add(1,l,mid,l,y-1,1);
		}
		if(z<x){
			tr[2].add(1,l,mid,z,x-1,ma);
			if(l<z)tr[3].add(1,l,mid,l,z-1,1);
		}
		while(lsw<cnt&&qry[id][lsw].r==i){
			if(qry[id][lsw].l>mid||qry[id][lsw].l==l&&qry[id][lsw].r==r){lsw++;continue;}
			for(int t=0;t<4;t++) add1(ans[qry[id][lsw].id],tr[t].qry(1,l,mid,qry[id][lsw].l,mid));
			lsw++;
		}
	}
	for(int i=0;i<4;i++) add1(f[id],tr[i].qry(1,l,mid,l,mid));
	for(int i=0;i<cnt;i++){
		if(qry[id][i].l==l&&qry[id][i].r==r) continue;
		if(qry[id][i].r<=mid) qry[lid].push_back(qry[id][i]);
		else if(qry[id][i].l>mid) qry[rid].push_back(qry[id][i]);
		else{
			qry[lid].push_back((query){qry[id][i].l,mid,qry[id][i].id});
			qry[rid].push_back((query){mid+1,qry[id][i].r,qry[id][i].id});
		}
	}
	solve(lid,l,mid),solve(rid,mid+1,r);
	add1(f[id],add2(f[lid],f[rid]));
	for(int i=0;i<cnt;i++)if(qry[id][i].l==l&&qry[id][i].r==r) add1(ans[qry[id][i].id],f[id]);
}
inline void file(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
}
int main(void){
	//file();
	n=read(),m=read();
	for(int i=1;i<=n;i++) s[i]=read();
	for(int i=1;i<=m;i++){
		qry[1].push_back((query){read(),read(),i});
	}
	solve(1,1,n);
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

``

标签:int,T4,mid,21.10,qry,rid,lz,id
来源: https://www.cnblogs.com/zyw4347/p/15364879.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有