题解 P4744 【[Wind Festival]Iron Man】
我又来写毒瘤题解啦
我们一看这题,哇,我会网络流!
网络流:什么鬼?管我什么事?
考虑建出这样一个图。
毒瘤思路毒瘤图
具体来说就是由
这样相当于我们完全模拟出了选
如果当
而这种选法不会出现。
对于这种情况,我们设这三条链的编号为
然后就可以开心敲代码了---吗?
有一个小问题。如果
顺便说一下如何求最长链:链长度翻一倍模拟环拆链,对于每个点维护前缀和,对于每一个点
不过话说dp好像也要用单调队列优化一下。
然后就可以开心敲代码啦~
#include <bits/stdc++.h>
#define rap(i,s,n) for(int i=s;i<=n;i++)
#define drap(i,n,s) for(int i=n;i>=s;i--)
#define N 210000
#define inf 0x3f3f3f3f
#define ll long long
#define m(s,k) memset(s,k,sizeof s)
using namespace std;
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) ((c>='0'&&c<='9')||(c=='-'))
template<typename T>
inline bool rd(T& xa){
char xchh; T f=1; while(xchh=getc(),(!isd(xchh))&&(xchh!=0));
if(xchh==0) return 0; if(xchh=='-') xchh=getc(),f=-1; xa=xchh-'0';
while(xchh=getc(),isd(xchh)) xa=xa*10+xchh-'0'; xa*=f; return 1;
}
int n,k,a[N],pre[N],ans;
struct mqueue{
//单调队列
int g[N],t[N],r,l;
void init(){r=0,l=1;}
void in(int x,int xt){while(r>=l&&g[r]>=x) r--; g[++r]=x,t[r]=xt;}
int tmin(){return t[l];} int gmin(){return g[l];}
void push(int xt){while(l<=r&&t[l]<=xt) l++;}
}q;
int main(){
rd(n); rd(k); rap(i,1,n) rd(a[i]);
int dk=0; rap(i,1,n) if(a[i]>0) dk++; if(dk<=k){
sort(a+1,a+n+1); drap(i,n,1){
if(k==0) break; ans+=a[i]; k--;
}
printf("%d\n",ans); return 0;
//特判
}
while(k--){
q.init(); int maxv=-inf,maxt=0,fx;
rap(i,1,n) a[i+n]=a[i],pre[i]=a[i]+pre[i-1],q.in(pre[i],i);
rap(i,n+1,2*n){
pre[i]=a[i]+pre[i-1];
if(maxv<pre[i]-q.gmin()) maxv=pre[i]-q.gmin(),maxt=i,fx=q.tmin();
q.in(pre[i],i); q.push(i-n);
}
//求出最长链 我为了方便写求的是左开右闭..
if(maxt==0) return 0; ans+=maxv;
rap(i,fx,maxt-1) a[i%n+1]=-a[i%n+1];
}
printf("%d\n",ans);
return 0;
}