【JOI2020 Final】火灾
【JOI2020 Final】火灾
Description
给定一个长为的序列,刚开始为时刻
定义时刻第个数为,那么:
你将对个操作进行评估,第个操作让时刻时的区间全部变为
执行一个操作需要一定的代价,执行第 个操作需要以下的代价:
求每个操作需要的代价
注意:每个操作都是独立的
Input
第一行两个整数代表序列长度和操作数
第二行个整数代表这个序列
接下来行每行三个整数代表一个操作
Output
行每行一个整数代表这个操作需要的代价
Sample Input
5 5
9 3 2 6 5
1 1 3
2 1 5
3 2 5
4 3 3
5 3 5
Sample Output
21
39
33
9
27
Data Constraint
Solution
比较有意思的数据结构题
以横坐标为位置,纵坐标为时间
把一个数作为最大值出现的坐标写出来
可以发现构成了一个平行四边形
其坐标可以通过单调栈得到
然后我们将平行四边形变为一个大三角形减去两个小三角形
可以发现,这里的三角形都是等腰直角三角形,而且底边都在轴上
所以我们只需要记录右上角的顶点
然后对询问差分,即变为两条射线,对每条射线统计经过位置的权值之和
做一点简单的观察,可以发现射线跟三角形的关系有三种
1.不交
2.射线顶点在三角形内部
3.射线完整穿过了三角形
后面两种都可以通过写出的关系,然后扫描线+树状数组维护
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define N 200010
LL ans[N];
int n,m,a[N],le[N],ri[N],q[N],top,tot,cnt;
struct node{int x,y,v;}op[N*3];
struct mode{int x,y,pos,k;}ask[N*2];
struct BIT{
LL sum[N*2];
int lowbit(int x){return -x&x;}
void change(int x,LL v){for(;x<=2*n+5;x+=lowbit(x))sum[x]+=v;}
LL query(int x){LL res=0;for(;x;x-=lowbit(x))res+=sum[x];return res;}
void clear(){memset(sum,0,sizeof(sum));}
}t1,t2;
bool cmp1(node x,node y){return x.x<y.x;}
bool cmp2(mode x,mode y){return x.x<y.x;}
int main(){
scanf("%d%d",&n,&m);
F(i,1,n)scanf("%d",&a[i]);
a[0]=a[n+1]=2147483647;
q[top=1]=0;
F(i,1,n){
while(a[i]>=a[q[top]]&&top)top--;
le[i]=q[top];q[++top]=i;
}
q[top=1]=n+1;
Fd(i,n,1){
while(a[i]>a[q[top]]&&top)top--;
ri[i]=q[top];q[++top]=i;
}
F(i,1,n){
// (i,0) (i,i-li-1) (ri-1,ri-i-1) (ri-1,ri-li-2)
int tmp=(le[i]?0:n);
if(ri[i]-le[i]-2+tmp>=0)op[++tot]=(node){ri[i]-1,ri[i]-le[i]-2+tmp,a[i]};
if(ri[i]-i-2>=0)op[++tot]=(node){ri[i]-1,ri[i]-i-2,-a[i]};
if(i-le[i]-2+tmp>=0)op[++tot]=(node){i-1,i-le[i]-2+tmp,-a[i]};
}
F(i,1,m){
int t,l,r;
scanf("%d%d%d",&t,&l,&r);
ask[++cnt]=(mode){r,t,i,1};
ask[++cnt]=(mode){l-1,t,i,-1};
}
// (x-y,0) (x,0) (x,y)
sort(op+1,op+tot+1,cmp1);
sort(ask+1,ask+cnt+1,cmp2);
int h=tot+1;
Fd(i,cnt,1){
while(op[h-1].x>ask[i].x&&h-1>=1){
h--;
t1.change(op[h].x-op[h].y+n,1ll*(op[h].x-op[h].y)*op[h].v);
t2.change(op[h].x-op[h].y+n,op[h].v);
}
LL tmp1=t1.query(ask[i].x-ask[i].y+n),tmp2=t2.query(ask[i].x-ask[i].y+n);
ans[ask[i].pos]+=(-tmp1+tmp2*(ask[i].x-ask[i].y+1))*ask[i].k;
}
t1.clear();t2.clear();
h=0;
F(i,1,cnt){
while(op[h+1].x<=ask[i].x&&h+1<=tot){
h++;
t1.change(op[h].y+5,1ll*op[h].y*op[h].v);
t2.change(op[h].y+5,op[h].v);
}
LL tmp1=t1.query(2*n+5)-t1.query(ask[i].y-1+5),tmp2=t2.query(2*n+5)-t2.query(ask[i].y-1+5);
ans[ask[i].pos]+=(tmp1-tmp2*(ask[i].y-1))*ask[i].k;
}
F(i,1,m)printf("%lld\n",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理