題目:
思路:看到這種找前後的題目... 第一反應就是拓撲排序_(:з」∠)_
每條線段都有左右兩個端點咯, 然後就亂搞吧..
我們用\(i\)和\(i'\)分別表示第\(i\)條線段的左右端點..
然後如果\(x\)在\(y\)的左邊, 那麼\(x'\)一定小於\(y\), 我們就建一條\(x'->y\)的邊
如果\(x\)與\(y\)相交, 那麼一定\(x且\(y(顯然), 我們就分別建\(x->y'\)和\(y->x'\)兩條邊.
然後對於每個點\(x\), \(x, 那麼再建\(x->x'\)的邊...
然後為了字典序, 把編號扔進乙個小根堆裡維護一下, 按照堆的順序跑一邊拓撲排序大約就可以了吧..
wrong的情況也很好特判, 只要判斷進隊的點的個數不到\(2n\)就好了...
輕鬆加愉快地過了樣例. 於是這樣就做完了?
然後非常無恥地找了一下資料一測, 發現得到了10pts... 就是輸出wrong的10分...
然後發現順序全錯了...這就很尷尬...
那就開啟組資料看一下嘛, 反正\(n\leq10\)的資料很適合手玩..
然後第二組資料(\(n\)最小的一組)是這樣的:
7 4
2 1 7
2 2 7
1 7 5
2 4 2
我們來畫一下:
就可以看出問題了. 如果我們這麼做,在\(x\)進堆之前, 若\(\exists\)邊\(y->x\)且\(\exists u滿足x, 則拓撲序列將變為\(u y x\)而不是\(y x u\), 字典序就不優了..(看清楚題目的字典序指的是什麼..)
那怎麼辦啊? 為了解決這個問題, 我們考慮把邊都反向, 堆變成乙個大根堆, 然後順序從後向前做(就是最後把拓撲序列倒過來), 就可以了..
因為我們發現, 這麼一搞, 存在依賴的編號較小的點將會比較靠後的彈出, 倒過來就變成優先了, 也就滿足了字典序的要求..
然後想到這一點就沒什麼難度了...
std好像用了手寫堆, 但是我人懶就直接上priority_queue咯, 不過跑的還是飛快, 最大的點也用不到0.3s..
**:
#include #include #include using namespace std;
const int n=202020;
priority_queueq;
inline int gn(int a=0,char c=0)
struct edgee[n];
int v[n],du[n],ans[n],tot,cnt,n,m;
inline void buildedge(int x,int y)
int main()n<<=1;
for(int i=1;i<=n;++i)
if(!du[i]) q.push(i); cnt=n;
while(!q.empty())
ans[x]=cnt--;
} if(cnt) puts("wrong");
else for(int i=1;i<=n;i+=2)
printf("%d %d\n",ans[i],ans[i+1]);
}
5 11返校測試T2
有k k第一行乙個整數n。第二行有n個正整數,每個數字代表一張選票所選的人的編號。每行乙個正整數,為優勝者的編號,由小到大。如果沒人獲勝,則輸出 no such person.8 5 2 3 6 2 5 2 72優勝者為2號。下面是這個題的思路qwq 將所有的選票進行從小到大排序 快排解決 然後將陣...
2018 10 27測試T2 洗衣服
傳送門 一道貪心題,但考場上沒貪出來 維護兩個堆,分別存洗衣服和烘乾衣服的時間 每次加進來一件衣服,就在之前最早結束的那一台機器裡操作,這樣會是最優的 洗衣服和烘乾衣服都這樣搞,最後再用最大配最小的原則求最大值就行了 include include include include define n ...
2018 11 02測試T2 飛越行星帶
傳送門 這道題比較妙啊 把每個行星看成乙個點 把 x xx 軸和 y l y ly l 看成兩個特殊的點 把行星之間的距離看做邊 每個點與 x xx 軸的邊為 y iy i yi 與 y l y ly l 的邊為 l y il y i l yi 從小到達加邊,如果發現 x xx 軸和 y l y l...