线段树+贪心算法(区间修改)
#include<bits/stdc++.h>
using namespace std;
int minn[200005*4];
int arr[200005];
int lazy[200005*4];
void push_down(int rt)
{
if(!lazy[rt])
return;
lazy[2*rt]+=lazy[rt];
lazy[2*rt+1]+=lazy[rt];
minn[2*rt]-=lazy[rt];
minn[2*rt+1]-=lazy[rt];
lazy[rt]=0;
return;
}
void build(int rt,int l,int r)
{
if(l==r)
{
minn[rt]=arr[l];
return ;
}
int mid=(l+r)/2;
build(2*rt,l,mid);
build(2*rt+1,mid+1,r);
minn[rt]=min(minn[2*rt],minn[2*rt+1]);
return;
}
long long query(int rt,int L,int R,int l,int r)
{
if(L<=l&&R>=r)
{
return minn[rt];
}
push_down(rt);
int mid=(l+r)/2;
long long ans=1e18;
if(L<=mid)
ans=min(ans, query(2*rt,L,R,l,mid));
if(R>mid)
ans=min(ans,query(2*rt+1,L,R,mid+1,r));
return ans;
}
void update(int rt,int L,int R,int l,int r,int c)
{
if(L<=l&&R>=r)
{
lazy[rt]+=c;
minn[rt]-=c;
return;
}
push_down(rt);
int mid=(l+r)/2;
if(L<=mid)
update(2*rt,L,R,l,mid,c);
if(R>mid)
update(2*rt+1,L,R,mid+1,r,c);
minn[rt]=min(minn[2*rt],minn[2*rt+1]);
return;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<n;i++)
{
cin>>arr[i];
}
build(1,1,n-1);
pair<int,int>p[200005];
for(int i=0,l,r;i<m;i++){
cin>>l>>r;
if(l>r) swap(l,r);
p[i]={r,l};
}
sort(p,p+m);
long long sum=0;
for(int i=0;i<m;i++){
int num=query(1,p[i].second+1,p[i].first,1,n-1);
sum+=num;
update(1,p[i].second+1,p[i].first,1,n-1,num);
}
cout<<sum;
return 0;
}