1 条题解

  • 9
    @ 2025-3-13 11:31:30

    反悔贪心。

    先建链表,每次找最大的,把他拿出来,如果标记过就跳过,然后为了反悔把“左边的+右边的-当前的”放进去,最后把他左右两边相邻的标记掉,再把他左指针连上左边的左边,他的右指针连上右边的右边。现在再把左边的右指针连他,右边的左指针连他,就做完了。

    #include<bits/stdc++.h>
    #define int long long
    #define R(x) x=read()
    #define N 200005
    using namespace std;
    inline int read() {
    	int x=0,y=1;
    	char e=getchar();
    	while(e<'0'||e>'9') {
    		if(e=='-')y=-1;
    		e=getchar();
    	}
    	while(e>='0'&&e<='9') {
    		x=(x<<1)+(x<<3)+(e-'0');
    		e=getchar();
    	}
    	return x*y;
    }
    int n,k,a[N];
    int lst[N],nxt[N];
    bool vis[N];
    priority_queue<pair<int,int> >q;
    signed main() {
    	R(n),R(k);
    	for(int i=1; i<=n; ++i) {
    		R(a[i]),lst[i]=i-1,nxt[i]=i+1;
    		if(i==1)lst[i]=n;
    		if(i==n)nxt[i]=1;
    		q.push({a[i],i});
    	}
    	if(n/2<k) {
    		cout<<"No solution!\n";
    		return 0;
    	}
    	int cnt=0,ans=0;
    	while(!q.empty()&&cnt<k) {
    		int i=q.top().second;
    		if(vis[i]) {
    			q.pop();
    			continue;
    		}
    		++cnt,ans+=q.top().first;
    		q.pop();
    		vis[lst[i]]=1,vis[nxt[i]]=1;
    		a[i]=a[lst[i]]+a[nxt[i]]-a[i];
    		q.push({a[i],i});
    		nxt[i]=nxt[nxt[i]],lst[i]=lst[lst[i]];
    		lst[nxt[i]]=i;
    		nxt[lst[i]]=i;
    	}
    	cout<<ans;
    	return 0;
    }
    
    
    • 1

    信息

    ID
    75
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    (无)
    递交数
    45
    已通过
    10
    上传者