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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

HDU - 6982 J - Road Discount wqs二分 + 模型转换 + 优化

發(fā)布時(shí)間:2023/12/4 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 6982 J - Road Discount wqs二分 + 模型转换 + 优化 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送門

文章目錄

  • 題意:
  • 思路:

題意:

給你一個(gè)nnn個(gè)點(diǎn)mmm條邊的圖,每個(gè)邊有一個(gè)代價(jià)以及折扣價(jià),你需要輸出nnn行,第iii行代表你可以選i?1i-1i?1條邊使其變成優(yōu)惠價(jià),問(wèn)每次的最小生成樹的代價(jià)是多少。
n≤1e3,m≤2e5,ci,di≤1e3n\le 1e3,m\le2e5,c_i,d_i\le 1e3n1e3,m2e5,ci?,di?1e3

思路:

直接考慮折扣價(jià)不是很好想,所以考慮能不能把這些邊單獨(dú)拿出來(lái)。
下面我們假定原邊是白邊,折扣邊是黑邊,那么對(duì)于每次要輸出的,問(wèn)題就轉(zhuǎn)換成了選kkk條黑邊的最小生成樹的代價(jià)是多少。
顯然這是一個(gè)wqswqswqs二分的一個(gè)經(jīng)典問(wèn)題,我們?cè)O(shè)這個(gè)函數(shù)是f(k)f(k)f(k),這是一個(gè)凸函數(shù),我們二分一個(gè)值midmidmid,之后將所有黑邊的權(quán)值都加上midmidmid,讓后跑最小生成樹,假設(shè)選擇了cntcntcnt條黑邊,且總代價(jià)是sumsumsum,那么如果cnt>=kcnt>=kcnt>=k的話,顯然可以更新ans=sum?k?midans=sum-k*midans=sum?k?mid ,讓后調(diào)整一下左右邊界即可。
直接跑的話復(fù)雜度是O(nmlognlogn)O(nmlognlogn)O(nmlognlogn)的,雖然第二個(gè)logloglog是最小生成樹的,常數(shù)很小,但仍是過(guò)不了,考慮優(yōu)化。
考慮每次都有很多無(wú)用邊,即非樹邊是無(wú)用的,所以直接去掉非樹邊即可,將邊縮小到O(n)O(n)O(n)級(jí)別的,但是n2lognlognn^2lognlognn2lognlogn想過(guò)這個(gè)有101010個(gè)測(cè)試點(diǎn)的題還是不可能的。
繼續(xù)優(yōu)化,考慮對(duì)于每次二分,他的信息是可以復(fù)用的,且邊權(quán)在[1,1000][1,1000][1,1000]范圍內(nèi),所以可以預(yù)處理出來(lái),之后每次查詢二分的話直接使用已有信息即可。
復(fù)雜度O(n2a+nlogn)O(n^2a+nlogn)O(n2a+nlogn),其中n2an^2an2aaaa是并查集的常數(shù),很小。

// Problem: J - Road Discount // Contest: Virtual Judge - 2021多校第三場(chǎng)補(bǔ)題 // URL: https://vjudge.net/contest/449636#problem/J // Memory Limit: 524 MB // Time Limit: 6000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #include<random> #include<cassert> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid ((tr[u].l+tr[u].r)>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n,m; int p[N],ans,cnt; PII f[N]; struct Node {int x,y,w,add,op;bool operator < (const Node &W) const {return w<W.w;} }edge1[N],edge2[N],edge[N];int find(int x) {return x==p[x]? x:p[x]=find(p[x]); }PII check(int mid) {for(int i=1;i<=m;i++) edge2[i].w+=mid;int tot=0;edge1[m+1].w=INF; edge2[m+1].w=INF;for(int i=1,j=1;i<=m||j<=m;) {if(edge1[i].w<edge2[j].w) edge[++tot]=edge1[i++];else edge[++tot]=edge2[j++];}cnt=0; ans=0;for(int i=1;i<=n;i++) p[i]=i;for(int i=1;i<=tot;i++) {int a=edge[i].x,b=edge[i].y,w=edge[i].w,op=edge[i].op;int pa=find(a),pb=find(b);if(pa==pb) continue;p[pa]=pb; cnt+=op==0;ans+=w;}for(int i=1;i<=m;i++) edge2[i].w-=mid;return {cnt,ans}; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);int _; scanf("%d",&_);while(_--) {scanf("%d%d",&n,&m);for(int i=1;i<=m;i++) scanf("%d%d%d%d",&edge1[i].x,&edge1[i].y,&edge1[i].w,&edge1[i].add),edge1[i].op=1;for(int i=1;i<=m;i++) {edge2[i]=edge1[i],edge2[i].w=edge1[i].add;edge2[i].op=0;}sort(edge1+1,edge1+1+m); sort(edge2+1,edge2+1+m);int tot=0;for(int i=1;i<=n;i++) p[i]=i;for(int i=1;i<=m;i++) {int a=edge1[i].x,b=edge1[i].y,w=edge1[i].w,op=edge1[i].op;int pa=find(a),pb=find(b);if(pa==pb) continue;p[pa]=pb; edge1[++tot]=edge1[i];}tot=0;for(int i=1;i<=n;i++) p[i]=i;for(int i=1;i<=m;i++) {int a=edge2[i].x,b=edge2[i].y,w=edge2[i].w,op=edge2[i].op;int pa=find(a),pb=find(b);if(pa==pb) continue;p[pa]=pb; edge2[++tot]=edge2[i];}m=n-1;for(int i=-1010;i<=1010;i++) f[i+1010]=check(i);for(int k=0;k<n;k++) {int l=-1010,r=1010,res;while(l<=r) {int mid=(l+r)/2;if(f[mid+1010].X>=k) res=f[mid+1010].Y-mid*k,l=mid+1;else r=mid-1;}printf("%d\n",res);}}return 0; } /**/ 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的HDU - 6982 J - Road Discount wqs二分 + 模型转换 + 优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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