1. 程式人生 > >[World Final 2016] Branch Assignment

[World Final 2016] Branch Assignment

連結

PDF

bzoj

先求出正置邊和反置邊時b+1到前b個點的最短路dis[0/1][x](x∈[1,b]),

令D[x]=dis[0][x]+dis[1][x]

然後分組後每個x對代價的貢獻為D[x]*(所在組中元素個數-1)

考慮DP決策分組過程,發現沒有一個很好的序,

不過為了使得代價小,應該把D小的放在個數大的組裡,D大的放在個數少的組裡

由此可以想出,應該是大小相近的元素放在了同一組中,這意味著,先排序,在劃分成s段,的所有情況包含了原問題的最優解

於是把D[1~b]排序後,有方程

$f[i][j]=MIN_{k=0}^{j-1}[f[i-1][k]+(j-k-1)*(sum[j]-sum[k])]$

$O(n^3)$

其中:f[i][j]表示把前j個分成i組的最小值,sum為D的字首和

非法狀態均置為INF

由於可以粗略的知道這個東西在j確定,i為自變數的函式影象上有凸性

(可以玄學地認為,最開始的時候,多劃分一刀可以造成很大的改變,隨著劃分次數越來越多,多劃分一刀的改變越來越微小)

於是,可以使用帶權二分來優化這一DP

即,消去對劃分次數的限制,通過二分來找到一個合適的劃分附加代價,使得即使不限制劃分次數,最後的最優解也恰好滿足我們對劃分數的限制

這樣有了一個新的方程

$f'[j]=MIN_{k=0}^{j-1}[f'[k]+(j-k-1)*(sum[j]-sum[k])]+C$

$O(n^2log)$

考慮優化轉移過程

拆開方程得到

$f'[j]=MIN_{k=0}^{j-1}[f'[k]+(k+1)sum[k]-ksum[j]-jsum[k]]+(j-1)sum[j]+C$

在方程中

當固定j不動時

隨k增加,f'[k]+(k+1)sum[k]項增加,而-ksum[j]-jsum[k]項減小

所以,隨j的增加,j的最優決策中的k會單調後移

這意味著這個方程有決策單調性

本題通過帶權二分和決策單調性優化可以做到$O(nlog^2)$

(感覺最近狀態很差,午休一直睡不著來著,幾個月了吧,先是用N^2log給方哥號上貢獻了半屏T,又以為可以nlog做,然後貢獻了半屏Wa,最後才發現決策單調性)

程式碼:

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define LL long long
  6 #define P pair <int ,int >
  7 using namespace std;
  8 priority_queue <P ,vector <P > ,greater <P > > PQ ;
  9 int n,b,s,r;
 10 struct INP{
 11     int u,v,val;
 12 }inp[50010];
 13 struct ss{
 14     int to,next,val;
 15 }e[50010];
 16 int first[5010],num;
 17 LL d[5010],f[5010],sum[5010];
 18 int lin[5010],dis[5010],que[5010],grt_st[5010];
 19 void build(int ,int ,int );
 20 void dij(int );
 21 bool check(LL );
 22 LL ask(int ,int );
 23 int main()
 24 {
 25     int i,j,k,l;
 26     LL L,R,mid;
 27     scanf("%d%d%d%d",&n,&b,&s,&r);
 28     for(i=1;i<=r;i++){
 29         scanf("%d%d%d",&inp[i].u,&inp[i].v,&inp[i].val);
 30         build(inp[i].u,inp[i].v,inp[i].val);
 31     }
 32     dij(b+1);
 33     for(i=1;i<=b;i++)    d[i]=dis[i];
 34     memset(first,0,sizeof(first)),num=0;
 35     for(i=1;i<=r;i++)
 36         build(inp[i].v,inp[i].u,inp[i].val);
 37     dij(b+1);
 38     for(i=1;i<=b;i++)    d[i]+=dis[i];
 39     sort(d+1,d+b+1);
 40     for(i=1;i<=b;i++)    sum[i]=sum[i-1]+d[i];
 41     L=0,R=b*sum[b],mid=(L+R)>>1;
 42     while(R-L>=3){
 43         if(check(mid))  L=mid;
 44         else    R=mid-1;
 45         mid=(L+R)>>1;
 46     }
 47     for(mid=R;mid>=L;mid--)
 48         if(check(mid)){
 49             printf("%lld\n",f[b]-s*mid);
 50             return 0;
 51         }
 52     return 0;
 53 }
 54 void build(int f,int t,int val){
 55     e[++num].next=first[f];
 56     e[num].to=t,e[num].val=val;
 57     first[f]=num;
 58 }
 59 void dij(int S){
 60     int i,U;
 61     memset(dis,0x3f,sizeof(dis));
 62     dis[S]=0;
 63     P u,v;
 64     u.first=0,u.second=S;
 65     PQ.push(u);
 66     while(!PQ.empty()){
 67         u=PQ.top();
 68         PQ.pop();
 69         U=u.second;
 70         for(i=first[U];i;i=e[i].next)
 71             if(dis[e[i].to]>dis[U]+e[i].val){
 72                 dis[e[i].to]=dis[U]+e[i].val;
 73                 v.first=dis[e[i].to],v.second=e[i].to;
 74                 PQ.push(v);
 75             }
 76     }
 77 }
 78 bool check(LL lim){
 79     int tmp=0,i,h=0,t=1;
 80     int l,r,mid;
 81     f[0]=lin[0]=0,grt_st[0]=1;
 82     que[t]=0;
 83     for(i=1;i<=b;i++){
 84         l=h+1,r=t,mid=(l+r)>>1;
 85         while(r-l>3){
 86             if(i>=grt_st[que[mid]])    l=mid;
 87             else    r=mid-1;
 88             mid=(l+r)>>1;
 89         }
 90         for(mid=r;mid>=l;mid--)
 91             if(i>=grt_st[que[mid]]){
 92                 f[i]=ask(i,que[mid])+lim,lin[i]=lin[que[mid]]+1;
 93                 break;
 94             }
 95         if(i==b)    break;
 96         grt_st[i]=b+1;
 97         while(h<t&&grt_st[que[t]]>i&&ask(grt_st[que[t]],i)<=ask(grt_st[que[t]],que[t]))    grt_st[i]=grt_st[que[t]],t--;
 98         if(h<t){
 99             l=max(grt_st[que[t]],i+1),r=grt_st[i]-1,mid=(l+r)>>1;
100             while(r-l>3){
101                 if(ask(mid,i)<=ask(mid,que[t]))    r=mid;
102                 else    l=mid+1;
103                 mid=(l+r)>>1;
104             }
105             for(mid=l;mid<=r;mid++)
106                 if(ask(mid,i)<=ask(mid,que[t])){
107                     grt_st[i]=mid;
108                     break;
109                 }
110         }
111         if(grt_st[i]!=b+1)
112             que[++t]=i;
113     }
114     return lin[b]>=s;
115 }
116 LL ask(int x,int typ){
117     return f[typ]+(x-typ-1)*(sum[x]-sum[typ]);
118 }

相關推薦

[World Final 2016] Branch Assignment

連結 PDF bzoj 先求出正置邊和反置邊時b+1到前b個點的最短路dis[0/1][x](x∈[1,b]), 令D[x]=dis[0][x]+dis[1][x] 然後分組後每個x對代價的貢獻為D[x]*(所在組中元素個數-1) 考慮DP決策分組過程,發現沒有一個很好的序, 不過為了使得代價小

2016 World Final K String Theory

題意: 遞迴定義了k-quotation是k個分號+若干個(k-1)-quotataion+k個分號,然後給你很多個分號,叫你求一下最大是多少quotation。 思路: 對於一個k-quotation,分號的字首形式肯定是(k)(k-1)(k-2)..(1)(1),然後後

2016 World Final F Longest Rivers

題意: 有n個河流@#¥……()……)—— 思路: 考慮河流i,讓他儘量排在最前的話,肯定是他直接走到根,對於其他的葉子節點,如果他比河流i短的話,他可以向上覆蓋一定的邊。所以,還有一些邊是沒有被覆蓋的, 對這些邊做一顆生成樹,那麼比這個河流長的河流個數就是1 + sum

2016 World Final D Clock Breaking

題意: 給一個LCD燈在一個連續時間內的燈的情況,要你確定哪些燈一定亮,一定暗和不確定。 思路: 先預處理出每個燈泡在24*60分鐘內的狀態,然後用給的時間內不是全亮也不是全暗的燈取匹配,如果沒有一個時間點能夠匹配,就是invalid。然後在考慮全亮或者全暗的燈,如果有一

“Hello World!”Final發布文案加美工

分享 分享圖片 .com 面向 簡要介紹 功能 font 原型 普通 文案: 大家好,我們是“Hello World!”團隊,本次我將向大家簡要介紹一下空天獵的final發布,在空天獵final發布中,我主要從以下兩個方面向大家進行介紹,第一個方面是增加了敵方的boss功能

LA 7578. ACM World Finals 2016 C. Ceiling Function

++ 樹的同構 acm iso pan eno func phi log 樹的同構 #include <iostream> using std::cin; using std::cout; using std::endl; struct treenode {

LA 7578. ACM World Finals 2016 L. Swap Space

fine scan def swa down struct sin algorithm turn 貪心 #include <cstdio> #include <algorithm> using std::sort; #define kN 10000

ACM-ICPC 2018 world final A題 Catch the Plane

題目連線:https://icpc.kattis.com/problems/catch Catch the Plane Your plane to the ICPC Finals departs in a short time, and the only way to get

Uva 1040 狀壓+搜尋 2005 ACM world final problem c

題目的隱含條件將這道題指向了最小生成樹; 利用類似prim的方法,列舉所有子圖並判斷是否包含詢問點,如果包含那麼可以更新答案; 邊統計邊更新,且由於更新一定是向更多的點狀態下更新,所以一定可以統計到答案,不至於到全部是inf的情況 再更新答案時記錄ps,pe兩個變數分別表示此狀態最後一次更新前的狀態,邊

World Final 2015 F. Keyboarding

Keyboarding 這是一道BFS(但用到了不少的SPFA的思想)的題,不過出題者十分毒瘤,有眾多坑點: 1、按下方向鍵時跳到下一個不同的字元,也就意味著游標可以“傳送”。 2、最後要列印一個回車,也就是“*”號。 3、選擇也是一次操作。 4、可能有多組資料。 5、因為同樣的字母會重複出現,所

解題:BZOJ 2673 World Final 2011 Chips Challenge

題面 資料範圍看起來很像網路流誒(滾那 因為限制多而且強,資料範圍也不大,我們考慮不直接求答案,而是轉化為判定問題 可以發現第二個限制相對好滿足,我們直接列舉這個限制就可以。具體來說是列舉所有行中的最大值$x$,然後下面那個式子移項就可以得到$a*tot>=b*x$,其中tot表示晶片的總數 然

2014ICPC World final A題(未解之謎)

未解之謎,先mark一下。 #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <iostream

World Final 1999 poj 1873 The Fortified Forest 狀壓列舉 凸包

2^15 的複雜度  直接列舉集合   但是...   poj tle uvaliva上ac的程式碼: //#include<iostream> #include<cmath> #include<cstdio> #include<

[World Final 2017 F] Posterize (DP)

菜雞選手只能刷刷水題了,這個題O(n^3)的dp還是很顯然的. #include <bits/stdc++.h> #define ll long long using namespace

2017 World Final專題

C:二分匹配使得至多的行列要求相同最多在同一個位置 #include<iostream> #include<cstring> #include<iostream> #include<cstdio> #include<

Gym 101194L / UVALive 7908 - World Cup - [三進制狀壓暴力枚舉][2016 EC-Final Problem L]

printf attach pre uvalive set 結果 題意 fin max 題目鏈接: http://codeforces.com/gym/101194/attachments https://icpcarchive.ecs.baylor.edu/index.p

2016 ACM-ICPC Asia China-Final D 二分

tdi post lib cpc src 是否 gpo clu -i 題意:一共有N個冰淇淋球,做一個冰淇淋需要K個球,並且由於穩定性,這K個球還必須滿足上下相鄰的下面比上面大至少兩倍。先給出N個球的質量,問最多能做出多少個冰淇淋? 思路:二分答案並對其檢

Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G題, 並查集 + 線段樹合並)

body end highlight 題目 efi 預處理 ++i sin const 題目鏈接 2016 ACM-ICPC EC-Final Problem G 題意 給定一個無向圖。每個點有一種顏色。    現在給定$q$個詢問,每次詢問$x$和$w$,求所有能

Number Theory Problem(The 2016 ACM-ICPC Asia China-Final Contest 找規律)

hide ever wan ace test spl res con ani 題目: Mr. Panda is one of the top specialists on number theory all over the world. Now Mr. Panda is

Bet(The 2016 ACM-ICPC Asia China-Final Contest 思路題)

suppose spec case cpc mon 輸入 under strong ces 題目:   The Codejamon game is on fire! Fans across the world are predicting and betting on wh