1. 程式人生 > >【BZOJ】3502 PA2012 Tanie linie

【BZOJ】3502 PA2012 Tanie linie

一位 == 可能 const ring 變化 過多 opened 個數

【算法】

【題解】

胡策k≤10的環狀DP做法:

1.欽定法:先確定第一位(可能和第n位)的狀態,然後後面正常做DP,顯然正確答案是一定會被記錄的,因為從整體上看不會有影響。

2.環的特性:取的段和不取的段數量相等,位置互補。所以1和n的連接處都選或都不選都會有不被包括的情況,一選一不選就和鏈一樣了。

正解貪心:

因為相鄰的正數或相鄰的負數肯定是要選一起選,所以點縮成正負正負…的數列形式,那麽考慮先選擇全部正的。

如果選擇的段數過多,考慮刪除則有兩種選擇:舍棄一個正數(相當於舍棄一個正數和兩個負數,把這三個數視為一個負數),選擇一個負數(相當於選擇一個負數和兩個正數,把這三個數視為一個正數)。

那麽顯然這兩種行為是等價的:都是合並相鄰的三個數字,可以視為對絕對值最小的數字操作最優,然後過程中用堆動態維護即可。

非環的情況特殊處理:不可能選擇頭尾的負數,因為沒辦法合並兩個正數,過程中需要判斷這個,而且這個頭尾還會變化。

對拍還是查找錯誤相當重要的方式!考試一定要寫暴力拍!

據說可以開頭特判一些東西跳掉沒用個數據——數據是死的,人是活的,出題人是懶的。

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1000010;

long long a[maxn],n,m,k,b[maxn],pre[maxn],suc[maxn];
bool f[maxn]; struct cyc { long long num,ord; bool p; bool operator <(const cyc &a) const { return num>a.num; } }qp; priority_queue<cyc>q; int main() { // freopen("input","r",stdin); scanf("%lld%lld",&n,&k); bool now=0;long long tot,m=0
; long long ans=0; scanf("%lld",&a[1]); b[(tot=1)]=a[1];now=a[1]>0; for(int i=2;i<=n;i++) { scanf("%lld",&a[i]); if(a[i]>0&&!now) { now=1; b[++tot]=a[i]; } else if(a[i]<=0&&now) { now=0; b[++tot]=a[i]; } else b[tot]+=a[i]; } // if((b[tot]>0)==(b[1]>0)&&tot!=1){b[1]+=b[tot];tot--;}//操作順序 for(int i=1;i<=tot;i++) { pre[i]=i-1;suc[i]=i+1; if(b[i]>0){ans+=b[i];m++;} q.push((cyc){(b[i]>0?b[i]:-b[i]),i,b[i]>0}); } // pre[1]=tot;suc[tot]=1; suc[tot]=0; long long en=tot,be=1; for(int i=m;i>k;i--) { while(f[q.top().ord]||((q.top().ord==be||q.top().ord==en)&&!q.top().p))q.pop(); qp=q.top();q.pop(); long long sum=0;long long A=pre[qp.ord],B=suc[qp.ord]; if(qp.p)sum=qp.num+b[A]+b[B]; else sum=b[A]+b[B]-qp.num; ans-=qp.num; if(suc[pre[A]])suc[pre[A]]=qp.ord;pre[qp.ord]=pre[A]; if(pre[suc[B]])pre[suc[B]]=qp.ord;suc[qp.ord]=suc[B]; f[A]=f[B]=1;b[qp.ord]=sum; //printf("ord=%lld num=%lld sum=%lld\n",qp.ord,qp.num,sum); if(B==en)en=qp.ord; if(A==be)be=qp.ord; q.push((cyc){(sum>0?sum:-sum),qp.ord,sum>0}); } printf("%lld",ans);//開long long return 0; }
View Code

【BZOJ】3502 PA2012 Tanie linie