私のZJOI
Day1
2017-3-21 07:52:53
有人在暴力膜
苟……
富貴
無相忘
ZJOI2017交流群 133135071
如果你足夠厲害
如果你足夠厲害
如果你足夠厲害
其實完全可以看那些大佬的ppt,分享見網址大佬ppt。
ps:其實本人就是抄抄他們ppt,下午最后一節課實在想睡覺就沒有認真聽了。。。滑稽.jpg
只不過好像有人抄我博客的樣子……這也是一種榮幸嘛……好不容易寫篇博客然后被抄,也在一種層面上說明我寫的博客寫得好吧。【逃……
但還是認准我的博客正文鏈接哦Hash大法好
以下正文
搜索專題
學軍中學 周子鑫
題目傳送門
- NOIP2012 普及組 文化之旅
- NOIP2015 提高組 斗地主
- NOI2010 方程的解數
- ZJOI2005 九數碼游戲
- Rikka with Sequence II
- 十五數碼問題
- SCOI2005 騎士精神
- NOIP2009 靶型數獨
- hdu4979 A simple math problem
- N皇后問題
- NOI2003 智破連環陣
- SDOI2015 排序
- 圍欄問題by dzy
- SRM555 MapGuessing(超級圖靈機)
- NOI1997 文件匹配
- NOI1998 軟件安裝盤
- NOI1999 生日蛋糕
- NOI2000 算符破譯
- ZJOI2014 璀燦光華
- ZJOI2014 2048
什么是搜索?-Was ist das?
存在
- 枚舉
- DFS
- BFS
- A*
- 回溯
- 蒙特卡洛樹
- 散列函數
- ……
(╯‵□′)╯︵┻━┻瞎幾把玩意兒!!
題目
NOIP2012 普及組 文化之旅
(聽說講課者當年只考了30分)
這道題第一眼看上去是NPC,這道題真的是NPC么。
是的。。
根據CCF的官方數據,有100中錯誤的方法能過掉這道題。比如,只考慮相鄰兩個城市之間的文化是否排斥,或者只考慮一條合法路徑。
正解:亂搜。
亂搞方法
- 搜索到一條路徑
- 倒着搜
- 去掉條件的一些條件
NOIP2015 提高組 斗地主
DFS過程中,不考慮單拍、對子、三個或者四個;搜索順序沒關系,最后貪心再來。
搜索中的通用優化
1.搜索折半搜索
例子:雙向廣搜從起點和終點交替搜;或者從兩邊搜索來。
NOI2010 方程的解數
將后面三項移到等式右邊,然后前面部分的M^3的時間內用hash存答案,后面三份也同樣,然后求出答案。
(可以用map)
ZJOI2005 九數碼游戲
從給出的矩陣和需要變成的矩陣,然后用hash記錄狀態;如果出現相同的hash,那么久搜到了。
Pikka with Sequence II
Way One
枚舉兩個點,作為中位數的貢獻點。
1 2 3 4 5 6 7 8
↑ ↑
中間的點都不用。但將左右兩邊放在一個集合。並且再賦一個±1的權值(中位數左邊賦成1,右邊是-1.然后就可以在集合中折半搜索。[復雜度明顯對了]
Way Two
枚舉選i個數,把序列分成兩半,然后就知道中位數落在那個位置,然后就可以和剛才一樣用歸並【其實並沒有聽懂】
2.啟發式搜索
- A*——BFS的啟發式版本
- IDA*——前者的迭代加深版
設置搜索上界,先看看搜十步能不能搜到答案;如果不能搜到,那就提高閾值。
引入估價函數,對每一個狀態x,f(x) = g(x) + h(x),其中g(x)是目前狀態的實際代價,而h(x)是目前狀態到目標狀態的估計代價。
為了保證正確性,h(x)不能大於當前狀態到目標狀態的最優值。
特殊的,當h(x) = 0時,A* 和 IDA* 算法退化成一般的BFS和迭代加深
十五數碼問題(八數碼問題的up版)
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15
一次移動只可能把有數字的移到空格,所以估價函數就用曼哈頓距離。
(限制:在……步數輸出-1之類的條件出現,那么
一定是IDA*!!!!!!
SCOI2005 騎士精神
玄學IDA*
3.Dancing Links(舞蹈鏈)
簡介:
解決一類覆蓋問題的通用框架,本質上只是常數優化,但非常強。
在交互式題目中還原上面的操作
雙向鏈表刪除節點操作
L[R[x]] <- L[x]
R[L[x]] <- R[x]
撤銷刪除操作:
L[R[x]] <- x
R[L[x]] <- x
題目(精確覆蓋)
給定一個由0和1組成的矩陣,問是否能找到一個行的集合,使得集合中的集合每一列都恰好都包含一個1.
Tag:精確覆蓋(DLX算法)
用Dangcing Links 可以常數優化。
什么玩意兒(╯‵□′)╯︵┻━┻
用U,D,L,R四個指針來表示每個1在矩陣中的關系
NOIP2009 靶型數獨
hdu4979 A simple math problem
N皇后問題
方案數:用公式O(1)
位運算優化:
- Matrix67博客
可以跑到N <= 13 - N<=1000爬山,模擬退火??(╯‵□′)╯︵┻━┻
- DLX算法:
每一行每一列的限制是精確覆蓋,而對角線上是對角線上最多有一個。於是方法就是先不管斜對角線的列[不用保證至少一個],所以只要搜索前面的精確覆蓋。
4.剪枝
NOI2003 智破連環陣
- dp求估價函數,
SDOI2015 排序
其實本道題只用看做一個線段樹一樣的東西。。交換內外層對方案數沒有影響。剪枝如下:
- 大層是連續遞增時,小塊不用交換。
- 選擇合法的交換方法就遞歸下去。
復雜度:T(4n*2)
圍欄問題by dzy
DLX
SRM555 MapGuessing(超級圖靈機)
集訓隊作業
NOI1997 文件匹配
NOI1998 軟件安裝盤
NOI1999 生日蛋糕
NOI2000 算符破譯
一塊塊的數字位數可以在枚舉算符位置之后進行可行性剪枝。
ZJOI2014 璀燦光華
ZJOI2014 2048
寫一個AI??恐懼……
但是直接爆搜,記憶化狀態,於是在20s時間和1G~2G內存中,A掉65536.
STL
杭州二中 陸宇暄
2017-3-21 14:00:41
題目傳送門
- BZOJ 3545 [ONTAK2012]Peaks
- Codeforces Round#85 D
- HNOI2009 夢幻布丁改變
默認該弄的東西:
#include<bits/std++.h>
using namespace std;
定義
iterator 迭代器(iter)
link 指針(lk)
function 函數(func)
node 指針(node)
(iterator和link差不多的)
不常用的算法庫函數
1.unique
去重
lk unique( lk begin, lk end );
2.nth_element
求出第k小的數
lk nth_element( lk begin, lk nth, lk end, func less );
3.自定義一個函數:
struct ex {
bool operator() (const node& a, const node& b) {
……
}
}
4.binary_search
返回bool類型
5.equal_range
pair<lk,lk>equal_range(lk begin, lk end, node val, func less );
6.lower_bound和upper_bound
神奇的東西
1.priority_queue
變成小根堆的方法:
priority_queue< int, vector<int>, greater<int> > Q;
2.set&map
平衡樹用set實現時,重載運算符。
遍歷map:
for( set<node>::iterator it = S.begin(); it != S.end(); ++ it )
啟發式合並。
3.vector
vector的push_back()實現方式:
先開一個小的數組,push_back()到一定程度之后,那么就再開辟一個兩倍的數組,然后copy進去。
所以復雜度是均攤O(1)
insert()操作
1e5次的vector的insert()和7e5次set的insert()速度差不多
但是開了O2並沒有變快。
更加神奇的東西
__gnu_cxx::hash_set
__gnu_cxx::hash_map
__gnu_cxx::rope
__gnu_pbds::priority_queue
__gnu_pbds::tree
1.__gnu_cxx::hash_set
hash實現set
頭文件:
include<ext/hash_set>
可以直接使用成set,但是唯一的區別是用iterator遍歷的時候不是有序的
(然而在hash表上維護一個鏈表,可以做到O(n)的遍歷)
然而,hash_set的實現時:
- 開一個大小為20的桶
- 如果沖突,那么就再開一個40的桶,重新hash一遍
hash表啟發式合並,復雜度O(logn)
hash_set< node, hash_er, e_qual >
func::hash_er{
……
}
e_qual{
……
}
__hash_map同理
常數不小,但是比set大。但還是建議自己寫。
2.__gnu_cxx::rope
include<ext/rope>
rope<node>
可支持一堆操作的字符串
可持久化平衡樹維護的序列
操作:
void push( node x )
void insert( int pos, node x )
void erase( int pos, node x )
void replace( int pos, node x )
rope <node> substr( int pos, int len )
node at( int x )
但是rope的復雜度是O(log(len))
【感覺和string類差不多的操作】
只要存一下歷史版本就可以持久化
可以當做可持久化數組用(但是常數有點大,內存要32倍用)
__gnu_pbd::priority_queue
include<ext/pb_ds/priority_queue.hpp>
_gnu_pbds::priority_queue< node, less<node>, head_tag >
可以搞各種各樣的堆。
heap_tag默認pairing_heap_tag
用法和std::priority_queue
a.join(b)
把a和b合並變成a,並把b清空(復雜度O(logn) )
point_iterator it = a.push(x)
a.erease(iter)
a.modify(iter, x)
事實上可以自己寫個左偏樹,但常數比手寫大一點。
__gnu_pbds::tree
include<ext/pb_ds/assoc_container.hpp>
include<ext/pb_ds/tree_policy.hpp>
tree<key,value,less<key>,tag=rb_tree_tag,tree_order_statistics_node_update >
//黑人問號.jpg
同樣
a.join(b)//同__gnu_pbds::priority_queue中的a.join(b)
a.split(key, b)//把b清空,然后把a中大於key的元素拆分到b
例題
二維點修改矩形求和
給定一個序列,
支持以下操作:修改一個元素,求第l個到第r個最早的一個w的位置
map< int, set< int > >
支持插入修改覆蓋翻轉循環位移的動態字符串
__gnu_cxx::rope
覆蓋的話,維護一個全A的rope,全B的rope,全C的rope……
翻轉就……維護兩個rope,一正一反
BZOJ 3545 [ONTAK2012]Peaks
__gnu_pbds::tree
CF85D
HNOI2009夢幻布丁
hash_set<int>
splay、線段樹的啟發式合並
水題選講
杭州二中 吳某某
2017-3-21 16:09:20
1.
- 你有一排n個水杯,每個水杯最多能裝mi的水,初始有si的水量,每秒增加ri的水量
- Q次詢問,每次詢問在事件t把[l, r]之間的水杯里的水喝完,並回答喝了多少水。
segment tree
相同時間被喝完的一段是可以通過二位數電直接計算這一段的貢獻。
喝完的水杯可以縮在一起
每次詢問之前將首尾的拆開
2.
- n個點( x1, y1 )
- 可以再每個點上建一個建築,這個建築是以該店為斜邊中心的等腰直角三角形,並且斜邊必須平行於x軸或y軸。
- 所有建築的邊長必須一樣,問最大邊長
- n<= 60
首先二分答案。
然后每個節點拆分成四個直角三角形。
然后簡單
3.
- 你有一個n * m的01矩陣
- 你可以翻轉任意一行或者任意一列
- 最小化最終矩陣中1的個數
- n<=20, m<=10^5
4.
- 給一張有向圖,Alex要從點1逃到點n,Bob在一些邊上設卡。
- 要求每個從點1到點n的路徑(路徑支持經過重復點)都只有一條邊設卡, 每條邊設卡有代價,問最小代價。
- n<=200, m<=2000
直接跑最小割,但是要建立一條反向的且代價無窮大的邊。
5.
- 給你一個字符串集合X
- 等幾率從字符串集合中挑出K個字符串(可以重復)並拼成一個大字符串
- 問S在大字符串中的期望出現次數
- |S| <= 500, |X| <= 50, |Xi| <= 50, K <= 1e12
暴力DP,f(i, j)balabala……
然而后面的就是Matrix Fast Power了
或者跑一個BM(什么東西(╯‵□′)╯︵┻━┻)
6.
- 給你一個DAG,有些節點是終止節點
- 求一個字符串的后綴自動機使得與該DAG同構
- 保證存在解
- n <= 200, m <= 2000
首先,DAG是什么??
考慮SAM的性質
顯然……