這題不難想到二分答案。。
你先對大小關係建乙個反圖,表示如果你想知道這個點,你必須先得到那個點的狀態
由於保證有解,所以這是乙個拓撲圖
然後你就拓撲排序地走。。
每乙個點就是連向它所有點的最小值,以及自己的時間,取乙個最小值值i,表示1~i它都可以選
策略,肯定是只要可以,就往後面放,正確性顯然
於是我們就要找在i前面的空位
這個顯然可以用乙個並查集來維護
對於當前點,你還要對你二分的答案取最小值
然後不合法情況就是存在乙個點沒有可以放的位置
然後就可以了
於是這個做法,時間複雜度是o(
nmlo
gn)
因為你每一次都要拓撲走一次。。
不知道有沒有常數好的人能過,反正我t了,對拍發現大概是正解的兩倍
然後我們繼續考慮優化,我們發現,對於同乙個點,無論二分答案是什麼,有許多東西的狀態都是固定的,就是拓撲序與他無關的
然後我們對於每乙個點,可以先跑半個圖,表示這些無論二分值為什麼都是不會變的,然後到時候就直接從一半開始跑,這樣就省時多了
時間複雜度o(
跑得過)
#include
#include
#include
#include
#include
#include
using namespace std;
const int max=1
<<30;
const int n=2005;
const int m=10005;
int n,m;
ints[n];
struct qq
e[m];int num,last[n];
int d[n];
void init (int
x,int
y)int d[n];
int lalal[n];//這個點在那個位置
int f[n];
int find (int
x)int
q[n];
inline int
read()
while(ch>='0'&&ch<='9')
return
x*f;
}int lalal[n];//一些預處理的
int dd[n];//也是一些預處理的
int f[n];
int st,ed;
int s,t;
bool check (int x,int shen)//排在這一位行不行
}// printf("tyb:%d
%d\n",st,ed);
while (st<=ed)
}st++;
}//printf("yes\n");
return true;
}void prepare (int now)
}while (st<=ed)
for (int i=last[x];i!=-1;i=e[i].last)}}
st++;
}/* printf("\nyes:");
for (int u=1;u<=n;u++) printf("%d ",lalal[u]);
printf("\n");*/
for (int i=1;i<=n;i++) lalal[i]=lalal[i];
for (int i=1;i<=n;i++) dd[i]=d[i];
for (int i=1;i<=n;i++) f[i]=f[i];
s=st;t=ed;
}int main()
for (int u=1;u<=n;u++) dd[u]=d[u]=d[u];
for (int u=1;u<=n;u++)
else l=mid+1;
}printf("%d ",ans);
}return
0;}
BZOJ 2535 Plane 航空管制2
題意 n個飛機一次出航。第i個飛機在出航序列中的序號不大於ki。另外有一些限制,表示飛機a的出航序號小於飛機b。1 輸出乙個合法的出航序列 2 輸出每個飛機最早的出航序號。思路 參考這裡。第一問比較好搞定。對於給出的,我們不妨建立有向邊。那麼b的所有孩子的出航序號必然小於b的出航序號。按照這個拓撲排...
NOI2010 航空管制
二元組的限制 考慮拓撲排序 正向拓撲不能保證最優,因卡的是結束時間 所以方向建圖topo 從n為0時間,相當於在n k i 的時間出現一架飛機 小根堆維護,每次選擇當前最早出現的一架飛機起飛。由於保證有解,這個顯然是正確的,對於當前只有一架飛機,不飛白不飛 當然也不能不飛 多架飛機,先飛後飛反正都是...
NOI2010 航空管制
首先第一問是很好做的,因為題目中保證有合法解,所以我們盡量讓期限晚的航班晚起飛.所以就是反著建圖,按照拓撲序給每個航班安排時間.第二問要求問所有合法解中每個航班最早什麼時候能起飛.那麼還是參考第一問的思路,額外的一點就是讓能安排在它後面的航班都安排到後面.所以就是先限制不選它,直到剩下的沒有辦法再選...