http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2415 この問題はかなり難しい。 グラフとして見ると一千六百万本の辺をもつグラフみたいなものだな。 どう格闘しても計算量が落ちないのでとりあえず重さが均等に二分割になるように切っていけば近似解を出せると考えて試作品コードを書いたところで力尽きた。 どうやって解こうかな? #include<stdio.h> #include<algorithm> #include<set> #define lli long long int struct B{ lli w; int p; bool operator<(const B& b)const{ return w<b.w; } }; std::set<B> memo; lli sums[4002],ans; lli saiki(int down,int up,lli herf){ if(down+1>=up)return sums[up]-sums[down]; B b; b.w=herf; std::set<B>::iterator it=memo.lower_bound(b); int p1=(*it).p; lli w1=(*it).w; lli wR=sums[up]-sums[p1-(herf!=w1)];//右側 lli wL=sums[p1]-sums[down];//左側 lli re=0; if(wL<wR){ re=saiki(down,p1,wL/2+sums[down]); re+=saiki(p1,up,wR/2+sums[p1]); }else{ re= saiki(p1-(herf!=w1),up,wR/2+sums[p1-(herf!=w1)]); re+=saiki(down,p1-(herf!=w1),wL/2+sums[down]); } ans+=re; return re; } int main(){ int n; lli w; std::set<B> body; B b; b.w=0; b.p=0; scanf("%d",&n); //memo.insert(b);//0番の番兵 for(int i=1;i<=n;i++){ scanf("%lld",&w); b.p=i; b.w+=w; sums[i]=b.w; memo.insert(b); } ans=0; saiki(0,n,sums[n]/2); printf("%lld\n",ans); }