[wc2005]友好的生物
還有2006陳啟峰的**:一張一弛,解題之道
part 2
先由簡,不考慮a[k],那麼這樣直接求怎麼求呢?
直接列舉o(n2k)當然可以,只不過會超時;
有沒有一種方法可以避免一些不必要的列舉呢?
這道題最大的阻礙就是這個絕對值問題了,因為它只跟兩個生物的具體屬性的相對大小有關,所以難以確定,必須列舉。
如果有辦法把他給確定了,問題就好解決了。
part 3
看看 k 的資料範圍,很容易想到可以從k下手;
抓住絕對值中的『-』是不變的,也就是說,同一屬性兩種生物的符號是相反的
有什麼用?(用處可大了)
說明對被減數取個負,他們的同一屬性的符號就一樣了呀。
這樣的話,對於每個符號方案,求出每個生物的屬性和,再相減不就可以了?
這個符號下放到每個屬性,一共就有2k-1種符號方案(先不考慮第k種)
你可能會說,這不一定是絕對值
但是這裡面一定包含絕對值,不是絕對值的答案一定會比正確答案小(廢話因為是負數)
part 4
列舉每一種符號方案(可以用狀壓01串表示+-),求出裡面的最大差就好,這個可以在o(n)的複雜度裡求出來;
邊列舉邊維護乙個min值,用當前值與min值得差更新答案,用當前值更新min值,這樣這道題的大致框架就出來了
part 5
考慮a[k],它取的是絕對值的相反數,怎麼考慮它呢?
如果它的符號也隨機,按照列舉來,這樣不能保證a[k]的貢獻為負貢獻,也不能保證最大差就是正確答案
那多出來的錯誤答案便是把a[k]弄成了正貢獻;
要避免這類情況。
他的特徵是小數減大數,我們需要一種方法,既滿足最大差就是正確答案,又滿足a[k]的性質;
不考慮a[k]的方法與生物的順序無關,與某一種屬性的大小也無關,但是a[k]就明顯與大小有關了
a[k]必須保證是小數減大數,而其他的屬性隨意,這樣就可以保證最大差就是正確答案;
既然a[k]與大小有關,不如就按照a[k]的大小確定加減,a[k]小的為被減數,而a[k]的符號確定為+。
這樣做能否保證上述方法的正確性呢?
這樣做,保證了第k種屬性對答案的貢獻為負,前面的符號仍然是列舉符號,而a[k]的符號確定,這樣再求最大差,仍然是滿足正確性
不如就按照a[k]的大小排序,保證a[k]大的在前面,只考慮減去比a[k]它大的生物,這樣就可以按照part 4的方法在o(n)的時間中求出最大差
題解:
1view code/***************************
2user:mandy.h.y
3language:c++
4problem:species
5algorithm:
6score:
7**************************
*/8 #include9
10using
namespace
std;
1112
const
int maxn = 1e5 + 5;13
const
int maxk = 6;14
15int
n,k,cur,ans,ans1,ans2,curid;
16int
c[maxk];
1718
struct
node
23}p[maxn];
2425 templateinline void read(t &x)
3132 templatevoid putch(const
t x)
3637 templatevoid put(const
t x)
4142
void
file()
4647
void
readdata()57}
58}
5960
void
work()
7071
for(int j = 2;j <= n; ++j)
77if(now - cur >ans)
8283
if(now
88}89 put(ans1);putchar('
');put(ans2);putchar('\n'
);90
put(ans);
9192}93
9495
intmain()
WC 2005 dface 雙面棋盤
其實就是個線段樹 並查集維護,原來的每行看做線段樹的乙個底層節點,線段樹每個節點2 n的空間建立乙個並查集,兩個節點合併時維護塊的個數資訊,然後捨棄中間部分保留外圍部分重建並查集就可以了。我寫的是zkw線段樹,用這方法就算不是黑白雙色也可以的吧。本人弱菜。include include includ...
WC2005 友好的生物
這題算是毒瘤吧,看到這個題我除了o n 2 想不到別的方法 後來嘗試使用平方的方式亂搞,但是給出了反例 在看了國家集訓隊ysy的解題報告後方才明白 思路是一種放寬的思路 我們列舉每個差值的符號,在其中列舉最大值,就可以有效去除絕對值 最後按照第k位從小到大排序,來列舉 從小到大進行掃瞄,每次用當前的...
Luogu2578 ZJOI2005 九數碼遊戲
狀態數不是很多,直接 bfs 輸出方案就記錄 pre 狀態即可 但是問題在於存狀態 可行的一些方案是 雜湊 map,康托展開 於是就學了一波康托展開 用康托展開的地方的地方感覺不會很多,畢竟要 n 2 算 大概意思就是給乙個排列 hash 計算出來的就是這個排列在所有 n 的排列中的排名 計算方式就...