HNOI2017影魔题解

HNOI2017 影魔

对于两种贡献,都只用考虑左边第一个比自己大的,和右边第一个比自己大的数,分别记为 liri

对于询问一,每个数对 (li,ri) 构成全部情况
对于询问二,可以拆分成 x=li 时,y[i+1,ri1] ,以及 y=ri 时,x[li+1,i1]

我们考虑用扫描线实现,将这些贡献离线下来排序,我们扫描右端点
对于第一种,在我们扫描到 ri 时,给 li 加上贡献
对于第二种,在我们扫描到 li 时,给 [i+1,ri1] 区间加,另一个同理
答案为区间 [l,r] 的和 (吗?)

我们会发现对于第二种情况的贡献我们可能会多算,于是我们可以在 扫描到 l1 的时候,给答案先减去此时的和,这样就对了

code

#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define int long long
int n,m,p1,p2,top,tot;
int a[N],qq[N],ans[N],c[N*4],tag[N*4],l[N],r[N];
struct A{
	int x,l,r,id,op;
}d[N*3],q[N*2];
bool cmp(A a,A b){
	return a.x<b.x;
}
void solve(){
	for(int i=1,t=0;i<=n;i++){
		while(t&&a[i]>a[qq[t]]) t--;
		l[i]=qq[t],qq[++t]=i;
	}
	qq[0]=n+1;
	for(int i=n,t=0;i>=1;i--){
		while(t&&a[i]>a[qq[t]]) t--;
		r[i]=qq[t],qq[++t]=i;
	}
	for(int i=1;i<=n;i++){
		if(l[i]&&r[i]<=n) d[++tot]={r[i],l[i],l[i],p1,i};
		if(l[i]&&r[i]!=i+1) d[++tot]={l[i],i+1,r[i]-1,p2,i};
		if(r[i]<=n&&l[i]!=i-1) d[++tot]={r[i],l[i]+1,i-1,p2,i};
	}
}
void jia(int p,int l,int r,int z){
	c[p]+=(r-l+1)*z,tag[p]+=z;
}
void down(int p,int l,int r,int mid){
	if(!tag[p]) return ;
	jia(p*2,l,mid,tag[p]),jia(p*2+1,mid+1,r,tag[p]),tag[p]=0;
}
void add(int p,int l,int r,int x,int y,int z){
	if(x<=l&&r<=y){
		jia(p,l,r,z);
		return ;
	}
	int mid=(l+r)>>1;
	down(p,l,r,mid);
	if(x<=mid) add(p*2,l,mid,x,y,z);
	if(mid<y) add(p*2+1,mid+1,r,x,y,z);
	c[p]=c[p*2]+c[p*2+1];
}
int sum(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y) return c[p];
	int mid=(l+r)>>1,ans=0;
	down(p,l,r,mid);
	if(x<=mid) ans+=sum(p*2,l,mid,x,y);
	if(mid<y) ans+=sum(p*2+1,mid+1,r,x,y);
	return ans;
}
signed main(){
	scanf("%lld%lld%lld%lld",&n,&m,&p1,&p2);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	solve();
	for(int i=1,l,r;i<=m;i++){
		scanf("%lld%lld",&l,&r);
		ans[i]+=(r-l)*p1,q[++top]={l-1,l,r,i,-1},q[++top]={r,l,r,i,1};
	} 
	sort(q+1,q+1+top,cmp);
	sort(d+1,d+1+tot,cmp);
	for(int i=1,j=1;i<=top;i++){
		while(d[j].x<=q[i].x&&j<=tot) add(1,1,n,d[j].l,d[j].r,d[j].id),j++;
		ans[q[i].id]+=q[i].op*sum(1,1,n,q[i].l,q[i].r);
	}
	for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
	return 0;
}
posted @   hubingshan  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示