HNOI 2016 D2T1 序列 (sequence)

http://yuxj173.github.io/2016/04/18/hnoi2016/#more

考场上唯一想出来的题,结果TM莫队写错了。。。

不过题解似乎有更神的莫队做法(优化过的莫队?)

不过块似乎分得有点问题,2S左右出解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int inf=(1e9)+7;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
typedef long long ll;
const int N=100000+5;
int b[N];
struct Query{
	int l,r,id;
	bool operator < (const Query &rhs)const{
		if(b[l]==b[rhs.l])return r<rhs.r;
		return b[l]<b[rhs.l];
	}
}q[N];
ll a[N];
int st[N][20],n,log_2[N];
bool cmp(int i,int j){
	return a[i]<a[j];
}
void rmq_init(){
	rep(i,1,n)st[i][0]=i;
	for(int j=1;(1<<j)<=n;j++)
	for(int i=1;i+(1<<j)-1<=n;i++)
	st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1],cmp);
}
int rmq(int l,int r){
	int k=log_2[r-l+1];
	return min(st[l][k],st[r-(1<<k)+1][k],cmp);
}
int pa[N];
int find(int x,ll y){
	return a[x]<y?x:pa[x]=find(pa[x],y);
}
ll res[N],depl[N],depr[N];
int que[N];
ll calcl(int l,int r){
	int pos=rmq(l,r);
	return a[pos]*(r-pos+1)+depr[l]-depr[pos];
}
ll calcr(int l,int r){
	int pos=rmq(l,r);
	return a[pos]*(pos-l+1)+depl[r]-depl[pos];
}
ll query(int l,int r){
	ll ans=0;
	rep(i,l,r)ans+=calcr(l,i);
	return ans;
}
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	int k;scanf("%d%d",&n,&k);
	rep(i,1,n)scanf("%lld",&a[i]);rmq_init();
	a[0]=a[n+1]=-inf;
	int tp;que[tp=0]=0;
	rep(i,1,n){
		while(a[i]<a[que[tp]])tp--;
		depl[i]=depl[que[tp]]+a[i]*(i-que[tp]);
		que[++tp]=i;
	}
	que[tp=0]=n+1;
	per(i,n,1){
		while(a[i]<a[que[tp]])tp--;
		depr[i]=depr[que[tp]]+a[i]*(que[tp]-i);
		que[++tp]=i;
	}
	int m=sqrt(n+0.5);
	rep(i,1,n)b[i]=(i-1)/m;
	rep(i,1,k)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
	sort(q+1,q+1+k);
	rep(i,2,n)log_2[i]=log_2[i>>1]+1;
	ll ans;b[0]=-1;
	int ql,qr,last=0;
	rep(i,1,k){
		if(b[q[i].l]==b[q[i].r])
		res[q[i].id]=query(q[i].l,q[i].r);
		else{
			ql=m*(b[q[i].l]+1);
			if(b[q[i].l]!=b[q[last].l])ans=0,qr=m*(b[q[i].l]+1)-1;
			while(qr<q[i].r)ans+=calcr(ql,++qr);
			ll tmp=ans;
			while(q[i].l<ql)tmp+=calcl(--ql,qr);
			res[q[i].id]=tmp;
			last=i;
		}
	}
	rep(i,1,k)printf("%lld\n",res[i]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值