日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)

發(fā)布時間:2025/3/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ.4738.[清华集训2016]汽水(点分治 分数规划) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

BZOJ
UOJ


\(val_i\)是每條邊的邊權(quán),\(s\)是邊權(quán)和,\(t\)是經(jīng)過邊數(shù),\(k\)是給定的\(k\)
在點分治的時候二分答案\(x\),設(shè)\(|\frac st-k|=x\),判斷是否還能滿足\(|\frac st-k|<x\)
因為是絕對值,分兩種情況:

  • \(\frac st-k\geq 0\to \sum val_i-k\geq 0\)
    判斷是否有\(\frac st-k< x\to\quad s-t*k<t*x\to\quad\sum val_i-k<t*x\)
  • \(\frac st-k<0\to\sum val_i-k<0\)
    判斷是否有\(\frac st-k>-x\to\quad s-t*k>-t*x\to\quad \sum val_i-k>-t*x\)
  • 先對每條邊的邊權(quán)\(val_i\)減掉一個\(k\)
    以第一種情況為例,就是求是否存在兩條路徑\(i,j\),使得\(s_i+s_j\geq 0\),且\(s_i+s_j<t_i*x+t_j*x\)
    \(DFS\)得到的子樹路徑信息存一個三元組\((s,t,anc)\),表示一條路徑的權(quán)值和、邊數(shù)、這條路徑來自哪棵子樹(兩條路徑拼起來的時候不能來自同一棵子樹)。
    然后把所有三元組按\(s\)從小到大排序。那從小到大枚舉\(i\),第一個滿足\(s_i+s_j\geq 0\)\(j\)的位置一定是單調(diào)遞減的,\(j\)后面(\(i\)之前)的路徑都滿足。
    所以維護兩個\(pair\),表示兩個\(s_k-t_k*x\)最小的、來自不同子樹的三元組\(A,B\)。找到第一個\(s_p>0\)的位置\(p\),令\(i=p,j=p-1\),然后隨著\(i\)的枚舉,更新一下\(A,B\),然后\(j\)也不斷往前移動順便更新\(A,B\)就可以了。每次對于\(i\),就把\(A,B\)\(k\),與\(i\)組合一下看是否可以滿足\(s_k-t_k*x<t_i*x-s_i\)
    具體看代碼吧,

    有兩種情況就二分\(x\)的時候,用兩個\(check\)判斷\(x\)\(\frac st -k\geq 0\))和\(-x\)\(\frac st-k<0\))是否有一個可行就行了。

    都是抄的一份代碼 常數(shù)差距怎么就那么大呢


    //6952kb 6680ms #include <cstdio> #include <cctype> #include <algorithm> #define mp std::make_pair #define pr std::pair<LL,int> //#define gc() getchar() #define MAXIN 300000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=5e4+5; const LL INF=1ll<<60;int cnt,Enum,H[N],nxt[N<<1],to[N<<1],Min,root,sz[N]; LL Ans,len[N<<1]; bool vis[N]; char IN[MAXIN],*SS=IN,*TT=IN; struct Node {LL s; int t,anc;inline bool operator <(const Node &x)const{return s<x.s;} }A[N];inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-48,c=gc());return now; } inline LL readll() {LL now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-48,c=gc());return now; } inline void AE(LL w,int u,int v) {Ans=std::min(Ans,std::abs(w));//abs!!!to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w; } void FindRoot(int x,int fa,int tot) {int mx=0; sz[x]=1;for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]&&v!=fa)FindRoot(v,x,tot), sz[x]+=sz[v], sz[v]>mx&&(mx=sz[v]);mx=std::max(mx,tot-sz[x]);if(mx<Min) Min=mx, root=x; } void DFS(int x,int fa,LL s,int dep,int anc) {A[++cnt]=(Node){s,dep,anc};for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]] && v!=fa) DFS(v,x,s+len[i],dep+1,anc); } inline void Upd(pr &x,pr &y,pr now) {if(now.first<y.first){if(now.first<x.first){if(now.second!=x.second) y=x;x=now;}else if(now.second!=x.second) y=now;} } bool Check1(LL k,int pos,int cnt) {pr x(INF,0),y(INF,0); A[0].s=-INF;for(int i=pos,j=pos-1; i<=cnt; ++i){while(A[i].s+A[j].s>=0) Upd(x,y,mp(A[j].s-k*A[j].t,A[j].anc)), --j;if((x.second==A[i].anc?y.first:x.first)+A[i].s<k*A[i].t) return 1;Upd(x,y,mp(A[i].s-k*A[i].t,A[i].anc));}return 0; } bool Check2(LL k,int pos,int cnt) {//s>-tx -> -s<txpr x(INF,0),y(INF,0); A[cnt+1].s=INF;for(int i=pos-1,j=pos; i; --i){while(A[i].s+A[j].s<0) Upd(x,y,mp(-A[j].s-k*A[j].t,A[j].anc)), ++j;if((x.second==A[i].anc?y.first:x.first)-A[i].s<k*A[i].t) return 1;Upd(x,y,mp(-A[i].s-k*A[i].t,A[i].anc));}return 0; } void Solve(int x) {vis[x]=1, A[cnt=1]=(Node){0,0,0};for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]) DFS(v,x,len[i],1,v);int p=1; std::sort(A+1,A+1+cnt), A[cnt+1].s=0;while(A[p].s<0) ++p;LL l=1,r=Ans,mid;//判斷是否存在比Ans小的答案 范圍是1~Ans!(UOJ數(shù)據(jù)真心強=-=)while(l<=r)if(Check1(mid=l+r>>1,p,cnt)||Check2(mid,p,cnt)) Ans=mid-1, r=mid-1;else l=mid+1;for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]) Min=N, FindRoot(v,x,sz[v]), Solve(root); }int main() {const int n=read(); const LL K=readll();//readll!!Ans=INF;//在這 不能在Solve()前面 = = for(int i=1; i<n; ++i) AE(readll()-K,read(),read());Min=N, FindRoot(1,1,n), Solve(root);printf("%lld\n",Ans);return 0; }

    轉(zhuǎn)載于:https://www.cnblogs.com/SovietPower/p/10322621.html

    總結(jié)

    以上是生活随笔為你收集整理的BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。