1 条题解

  • 0
    @ 2026-8-6 10:53:52

    糖飞了,题目是 0-index 所以修改操作的 bb 是要少加一个的。

    这题就是分块维护下凸壳然后二分斜率。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=2e5+10,M=1010;
    int a[N],tag1[M],tag2[M],n,B;
    struct node{int x,y;};
    vector<node>stk[M];int len[M];
    int cross(node n1,node n2,node n3){return (n2.x-n1.x)*(n3.y-n1.y)-(n2.y-n1.y)*(n3.x-n1.x);}
    void pushup(int x)
    {
    	len[x]=0;int bl=(x-1)*B+1,br=min(n,x*B);
    	for(int i=bl;i<=br;i++)
    	{
    		while(len[x]>1&&cross(stk[x][len[x]-1],stk[x][len[x]],{i,a[i]})<=0)len[x]--;
    		stk[x][++len[x]]={i,a[i]};
    	}
    }
    void upd(int l,int r,int b,int c)
    {
    	int bl=(l-1)/B+1,br=(r-1)/B+1;
    	if(bl==br)
    	{
    		for(int i=l;i<=r;i++)a[i]=a[i]+b*(i-1)+c;
    		pushup(bl);
    	}
    	else
    	{
    		for(int i=l;i<=bl*B;i++)a[i]=a[i]+b*(i-1)+c;
    		pushup(bl);
    		for(int i=(br-1)*B+1;i<=r;i++)a[i]=a[i]+b*(i-1)+c;
    		pushup(br);
    		for(int i=bl+1;i<br;i++)tag1[i]+=b,tag2[i]+=c;
    	}
    }
    int query(int l,int r)
    {
    	int bl=(l-1)/B+1,br=(r-1)/B+1,ans=1e18;
    	if(bl==br)
    	{
    		for(int i=l;i<=r;i++)
    			ans=min(ans,a[i]+tag1[bl]*(i-1)+tag2[bl]);
    	}
    	else
    	{
    		for(int i=l;i<=bl*B;i++)
    			ans=min(ans,a[i]+tag1[bl]*(i-1)+tag2[bl]);
    		for(int i=(br-1)*B+1;i<=r;i++)
    			ans=min(ans,a[i]+tag1[br]*(i-1)+tag2[br]);
    		for(int i=bl+1;i<br;i++)
    		{
    			int l=1,r=len[i],res=1;
    			while(l<=r)
    			{
    				int mid=(l+r)>>1;
    				if(mid==1||(stk[i][mid].x-stk[i][mid-1].x)*tag1[i]<stk[i][mid-1].y-stk[i][mid].y)
    					l=mid+1,res=mid;
    				else r=mid-1;
    			}
    			int idx=stk[i][res].x;
    			ans=min(ans,a[idx]+tag1[i]*(idx-1)+tag2[i]);
    		}
    	}
    	return ans;
    }
    signed main()
    {
    	cin>>n;B=sqrt(n);int q;cin>>q;
    	for(int i=1;i<=(n-1)/B+1;i++)stk[i].resize(B+10);
    	for(int i=1;i<=n;i++)cin>>a[i];
    	for(int i=1;i<=(n-1)/B+1;i++)pushup(i);
    	while(q--)
    	{
    		int op,l,r,b,c;cin>>op>>l>>r;l++;
    		if(op==0)
    		{
    			cin>>b>>c;
    			upd(l,r,b,c);
    		}
    		else cout<<query(l,r)<<'\n';
    	}
    	return 0;
    }
    • 1

    区间线性加区间最小值(Range Linear Add Range Min)

    信息

    ID
    8138
    时间
    1000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    11
    已通过
    2
    上传者