NOIP2015day2 運輸計劃(二分答案+差分/抽路+字首最大值)
題意
https://www.luogu.org/problemnew/show/P2680
思路
最大路徑最短,二分吧。。。然後就二分了,考試時
分,常數太大,邊界設的太大。
二分的邊界如果設的小,能大大減小常數,對於這道題,最長時間肯定不會長過最長路徑的值,短過最長路徑減整棵樹上的最長邊。這樣算一下頂多二分
次,血賺。
二分的
也比較清晰,對於一個給定的最短路最大值
,將
條路徑中長度超過
的都標記掉,考慮清掉一條被所有路徑覆蓋的邊的權值,如果存在清掉某條邊的權值,能使最長不合法的路徑長度不超過
,那麼這個
合法,嘗試更小的
。
但是
的常數很大,導致在比較慢的測評機上
,如果把
標記差分改成跳重鏈標記,看上去像多了一個
,實際上少了一個大常數,記住跳重鏈常數很小。
仔細觀察,如果清邊不刪在最長的給定路徑上的話,就沒什麼意義了,由此想到“抽出”最長路徑,然後將子樹掛在下面,這也是樹的一個很好的結構。
如果清除了某條邊的權值,不難發現只要對這條邊左邊子樹的最長路、右邊子樹的最長路、清完邊後拉出最長路的長度取
即可,所以在拉出路徑後維護一個字首、字尾最大值。
程式碼
二分答案+差分
#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
using namespace std;
const int N=3e5+3;
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],cost[maxm],nxt[maxm],tot;
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v,int w){to[++tot]=v,cost[tot]=w,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G;
int dep[N],fa[N],sz[N],son[N],top[N],ed[N],dis[N],dfn[N],ord,dif[N];
int X[N],Y[N],lca[N],Pt[N],n,m,maxer,maxed;
void dfs(int u,int f,int d,int D)
{
dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0,dis[u]=D;
EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(v==f)continue;
ed[v]=w;
dfs(v,u,d+1,D+w);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void make_path(int u,int f,int tp)
{
dfn[u]=++ord,top[u]=tp;
if(son[u])make_path(son[u],u,tp);
EOR(i,G,u)
{
int v=G.to[i];
if(v==f||v==son[u])continue;
make_path(v,u,v);
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void update(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
dif[dfn[top[x]]]++,dif[dfn[x]+1]--;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
dif[dfn[y]+1]++,dif[dfn[x]+1]--;
}
bool check(int k)
{
int cnt=0,maxcut=0;
memset(dif,0,sizeof(dif));
FOR(i,1,m)if(Pt[i]>k)
{
cnt++;
update(X[i],Y[i]);
}
FOR(i,1,n)dif[i]+=dif[i-1];
FOR(i,1,n)if(dif[dfn[i]]==cnt)
maxcut=max(maxcut,ed[i]);
return maxer-maxcut<=k;
}
int main()
{
G.clear();
scanf("%d%d",&n,&m);
FOR(i,1,n-1)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G.add(u,v,w);
G.add(v,u,w);
maxed=max(maxed,w);
}
dfs(1,0,1,0);
make_path(1,0,1);
FOR(i,1,m)
{
scanf("%d%d",&X[i],&Y[i]);
lca[i]=LCA(X[i],Y[i]);
Pt[i]=dis[X[i]]+dis[Y[i]]-2*dis[lca[i]];
maxer=max(maxer,Pt[i]);
}
int l=maxer-maxed,r=maxer,mid;
while(l<r)
{
mid=l+r>>1;
if(check(mid))
r=mid;
else l=mid+1;
}
printf("%d\n",l);
return 0;
}
抽路+字首最大值
#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
using namespace std;
const int N=3e5+3;
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],cost[maxm],nxt[maxm],tot;
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v,int w){to[++tot]=v,cost[tot]=w,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G;
int dep[N],fa[N],sz[N],son[N],top[N],dis[N];
int X[N],Y[N],Ds[N],n,m,maxer=-1;
int Pt[N],ed[N],ID[N],pref[N],suff[N],p,len,Fa[N];
void dfs(int u,int f,int d,int D)
{
dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0,dis[u]=D;
EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(v==f)continue;
dfs(v,u,d+1,D+w);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void make_path(int u,int f,int tp)
{
top[u]=tp;
if(son[u])make_path(son[u],u,tp);
EOR(i,G,u)
{
int v=G.to[i];
if(v==f||v==son[u])continue;
make_path(v,u,v);
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void dfs_mark(int u,int f)
{
EOR(i,G,u)
{
int v=G.to[i];
if(v==f)continue;
if(Fa[v])continue;
Fa[v]=Fa[u];
dfs_mark(v,u);
}
}
bool Draw(int u,int f,int To)
{
if(u==To)
{
Pt[++len]=u;
return 1;
}
EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(v==f)continue;
Pt[++len]=u,ed[len]=w;
if(Draw(v,u,To))return 1;
len--;
}
return 0;
}
int main()
{
G.clear();
scanf("%d%d",&n,&m);
FOR(i,1,n-1)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G.add(u,v,w);
G.add(v,u,w);
}
dfs(1,0,1,0);
make_path(1,0,1);
FOR(i,1,m)
{
scanf("%d%d",&X[i],&Y[i]);
Ds[i]=dis[X[i]]+dis[Y[i]]-2*dis[LCA(X[i],Y[i])];
if(Ds[i]>maxer)
{
maxer=Ds[i];
p=i;
}
}
Draw(X[p],0,Y[p]);
FOR(i
相關推薦
NOIP2015day2 運輸計劃(二分答案+差分/抽路+字首最大值)
題意
https://www.luogu.org/problemnew/show/P2680
思路
最大路徑最短,二分吧。。。然後就二分了,考試時
95
101889I Imperial roads (樹鏈剖分維護邊權最大值)
題意:給你一個圖,然後Q個詢問,每個詢問,問強制要求使用某條邊的情況下的最小生成樹。
解題思路:先求最小生成樹,然後對於強制要求的邊,直接查詢樹上路徑最大值,然後減去這個最大值,再加上要求的邊的權值就是答案。
直接上樹鏈剖分即可。
#includ
2018.11.05【NOIP2015】【洛谷2680】【UOJ#150】運輸計劃(二分答案+DFS序+樹上差分)或(複雜度並不對(也不能過)的樹鏈剖分)
洛谷傳送門
解析:
UOJ上的資料很強,複雜度不對過不了的,但是LCALCALCA如果是用倍增求的話也過不了(已經加了上界優化)。。。畢竟樹剖常數小,複雜度還不滿。。。
思路:
首先,不要試圖化邊為點,每條邊的資訊可以存在它所指向的兒子中。
解法1:UOJ上
【CodeForces954G】Castle Defense(二分答案+差分)
getc AD set urn char class pos ref ++i Description
題目鏈接
Solution
二分答案,套一個差分標記即可
每次放弓箭手顯然越右邊越優
Code
#include <cstdio>
#include <a
BZOJ 4326 運輸計劃(LCA +樹上差分)
任重而道遠
Description
公元 2044 年,人類進入了宇宙紀元。L 國有 n 個星球,還有 n?1 條雙向航道,每條航道建立在兩個星球之間,
這 n-1 條航道連通了 L 國的所有星球。小 P 掌管一家物流公司, 該公司有很多個運輸計劃,每個運輸計劃形如
:有一艘物流飛船
(java)leetcode852 山脈陣列的封頂索引(二分查詢法找出陣列中最大值的下標)(Peak Index in a Mountain Array)
題目描述:
我們把符合下列屬性的陣列 A 稱作山脈:
A.length >= 3
存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A
hdu 1024 Max Sum Plus Plus(動態規劃+m子段和的最大值)
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you ar
Max Sum Plus Plus (動態規劃+m子段和的最大值)
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you
P2680 運輸計劃 A-二分答案-樹上邊差分
https://www.luogu.org/problemnew/show/P2680
題意:首先這是一棵n個節點的樹,然後對於樹上的m條鏈,我們可以選取樹上的唯一一條邊使它的邊權變為0
求處理後最長鏈的長度,要求使得最後最長鏈長度最小,最大值最小問題,二分答案
思路:二分答
P1083 借教室-二分答案-差分陣列第二彈
https://www.luogu.org/problemnew/show/P1083
小結:差分陣列,一般並沒有裸的考查,但是差分陣列的思想啊,輔助啊,還是比較常用的
思路:二分答案,列舉最多多少訂單能夠合法。每次檢驗答案按照差分思想檢驗判斷當前訂單數是否超過原來的量
#
【LuoguP4926】倍殺測量者-二分答案+差分約束+判正環
測試地址:倍殺測量者
做法: 本題需要用到二分答案+差分約束+判正環。
對於第一種flag,用不等式表示:如果滿足xA≥(k−T)xBx_A\ge (k-T)x_BxA≥(k−T)xB就不用女裝;對於第二種flag,用不等式表示:如果滿足xA(k+T)&am
POI2010 Mos-Bridges(二分答案+歐拉回路+網路流)
【題目描述】
YYD 為了減肥,他來到了瘦海,這是一個巨大的海,海中有 n nn 個小島,小島之間有 m mm 座橋連線,兩個小島之間不會有兩座橋,並且從一個小島可以到另外任意一個小島。現在 YYD 想騎單車從小島 1 11 出發,騎過每一座橋,到達每一個小島,然後回到小島 1 11。霸中同學為
POJ 1064 Cable master (二分答案,G++不過,C++就過了)
題目:
這題有點坑,G++過不了,C++能過。
條件:n個數據a[],分成k段,結果精度要求兩位小數。
問題:每段最長為多少?
思路:因為精度要求為兩位小數,我先把所有的長度a[]*100。
我們對答案二分搜尋,把l設定為0,r設定為1000
Mr.Panda and TubeMaster Gym - 101194J (二分染色有源匯上下界最大費用流)
Mr.Panda and TubeMaster
Gym - 101194J
題目連結就這樣了,題面難得獲得就算了。
題目大意:
給出一面方格紙,上面佈滿了方格,方格中能且只能如下圖部署水管:
每兩個方格之間連線具有一定的收益,問在滿足所有的水管成環,
[ACM] POJ 3273 Monthly Expense (二分解決最小化最大值)
Monthly Expense
Time Limit: 2000MS
Memory Limit: 65536K
Total Submissions: 14158
Accepted: 5697
Description
Farmer John is an ast
POJ-2456 Aggressive cows---最大化最小值(也就是求最大值)
思路 cst target main include IT urn cstring strong 題目鏈接:
https://vjudge.net/problem/POJ-2456
題目大意:
有n個牛欄,選m個放進牛,相當於一條線段上有 n 個點,選取 m 個點, 使得相
單調隊列 —— 滑動窗口(滾動最大值)
簡單 保持 工作 影響 區間最值 因此 for 開始 += 一道經典的單調隊列題目——[洛谷P1886 滑動窗口]。(下文開始只討論求滾動的最大值)
暴力解法是O(n^2)的,對於每一個起點,搜一遍長度為k的子序列,求得最值—&mdas
算法學習——貪心算法之刪數字(求最大值)
size 算法學習 末尾 最小 條件 求最大值 sca 位數 技術 算法描述
在給定的n位數字,刪除其中的k位數字( k < n),使得最後的n-k為數字為最大值(原次序不變)
算法思路
考慮到是要移出數字,我們使用鏈表設計此算法較為方便,鏈表可以直接移出某個位
kuangbin專題七 HDU1754 I Hate It (單點修改維護最大值)
cond color include 專題 一次 span 修改 信息 \n 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的
Chip Factory (字典樹求異或最大值)
John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor