1 条题解

  • 0
    @ 2026-3-15 23:47:02

    此题数据范围如此之大,DP 正常情况下无法设计出合适的状态来解决此问题,考虑贪心。

    考虑当 k 极大的时候,答案一定是所有正数的和,考虑从反向考虑,也就是从“很多个段”变成“一个段”。

    容易发现,极大的连续非负段和极大连续负段总是同时选或者同时不选比较优秀,考虑把它们合并,问题变成一个正负交替数列,一开始你选了所有正的数,接下来你有两种操作:合并两个段(也就是加入两个段之间的那个为负的元素),删除一个段,而这可以直接用堆实现,

    #include<bits/stdc++.h>
    const int N=11e5;
    using namespace std;
    int n,t,c,k,p[N],s[N];
    bool no[N];
    long long g[N],w;
    priority_queue<pair<long long,int> >bbc;
    int main()
    {
    	cin>>n>>k;
    	for(int o=1,i=0,x;i<n;++i)
    	{
    		cin>>x;
            if(!i||x*o<0)++t,o=x<0?-1:1;
            g[t]+=x;
    	}
    	for(int i=1;i<=t;p[i]=i-1,s[i]=i+1,bbc.push(make_pair(-abs(g[i]),i)),++i)
    		if(g[i]>0)++c,w+=g[i];
    	s[t]=0; 
    	while(c>k)
    	{
    		int u=bbc.top().second,x=bbc.top().first;bbc.pop();
    		if(no[u])continue;
    		if(g[u]>0||(p[u]&&s[u]))
    		{
    			int pe=p[u],sf=s[u];
    			no[pe]=no[sf]=1,--c,w+=x,
    			g[u]+=g[pe]+g[sf],
    			bbc.push(make_pair(-abs(g[u]),u));
    			s[p[u]=p[pe]]=u;
    			p[s[u]=s[sf]]=u,p[0]=s[0]=0;
    		}
    	}
    	cout<<w;
    	return 0;
    }
    
    • 1

    信息

    ID
    5167
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者