F - Takahashi in Narrow Road
我们可以发现,每次操作后,对于一段变化后的区间,其变为了一段公差为1的等差数列,所以我们如果把每个值减去对应的下标,那么对应的区间变化后,都为一个相同的值,这样就可以使用区间推平,用线段树进行维护即可,然后根据题目信息,每次计算出变化区间的左端点和右端点即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
const int maxv = 4e6 + 5;
typedef pair<ll, ll> pll;
typedef array<int,3> ar;
// #define endl "\n"
int mod=1e9+7;
const int inf=0x3f3f3f3f;
struct node
{
ll l,r,sum,add;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sum(x) tr[x].sum
#define add(x) tr[x].add
}tr[N*4];
int a[N];
void update(int p)
{
sum(p)=sum(p*2)+sum(p*2+1);
}
void build(int p,int l,int r)
{
if(l==r){
tr[p]={l,r,a[l],0};
return ;
}
l(p)=l,r(p)=r;
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
update(p);
}
void pushdown(int p)
{
if(add(p)){
sum(p*2)=(r(p*2)-l(p*2)+1)*add(p);
sum(p*2+1)=(r(p*2+1)-l(p*2+1)+1)*add(p);
add(p*2)=add(p);
add(p*2+1)=add(p);
add(p)=0;
}
}
void modify(int p,int l,int r,int tag)
{
if(l<=l(p)&&r(p)<=r){
add(p)=tag;
sum(p)=(r(p)-l(p)+1)*tag;
return ;
}
pushdown(p);
int mid=(l(p)+r(p))/2;
if(l<=mid) modify(p*2,l,r,tag);
if(r>mid) modify(p*2+1,l,r,tag);
update(p);
}
ll query(int p,int l,int r)
{
if(l<=l(p)&&r(p)<=r){
return sum(p);
}
pushdown(p);
int mid=(l(p)+r(p))/2;
ll res=0;
if(l<=mid) res+=query(p*2,l,r);
if(r>mid) res+=query(p*2+1,l,r);
return res;
}
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],a[i]-=i;
int q;
cin>>q;
auto get=[&](int x,int l,int r)
{
int ans=0;
while(l<=r){
int mid=(l+r)/2;
if(query(1,mid,mid)>=x){
ans=mid,r=mid-1;
}
else l=mid+1;
}
return ans;
};
auto get1=[&](int x,int l,int r)
{
int ans=0;
while(l<=r){
int mid=(l+r)/2;
if(query(1,mid,mid)<=x){
ans=mid,l=mid+1;
}
else r=mid-1;
}
return ans;
};
ll ans=0;
build(1,1,n);
while(q--){
ll x,y;
cin>>x>>y;
y-=x;
ll val=query(1,x,x);
int l,r;
if(val<=y){
l=x,r=get1(y,x,n);
}
else{
l=get(y,1,x),r=x;
}
// cout<<val<<" "<<l<<" "<<r<<endl;
ans+=abs(query(1,l,r)-y*(r-l+1));
modify(1,l,r,y);
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin>>t;
while (t--)
{
solve();
}
system("pause");
return 0;
}