本來2維平面內的最接近點對問題是有O(nlogn)的演算法的,但那個分治演算法實用性不強盾盾想到了一個十分飄逸的演算法: 隨機旋一下系,按x排序然後直接裸找+break即可通常情況下直接按x排序裸找是會被某些數據卡到的(某些無聊的同學就不要說按y排之類的話了)但是,為什麼會被卡到?無非就是點全排在一排上就break不動了嘛!那我們隨機旋系不就隨便資料怎麼搞都不容易被卡到了吧!因此該演算法有O(快排+k*n)的複雜度,實際測試中該演算法的成績也相當不錯,求3維空間內最接近點對,n=100000
好久沒搞麻煩資料結構了,因此藉此題練練手,順便鞏固鞏固這神奇的動態樹題目大意很簡潔,就是要求你設計一個資料結構,支援3種操作:改一個邊的邊權,把i到j的路徑上所有邊取反,詢問i到j的路徑上的最大值題目很簡潔,思路自然也簡潔了,就動態樹強做嘛!但實現的時候,還是有一些技巧的,比方說取反,其實只要把i到根取反,再把j到根取反,自然就是把i到j取反了這裡我發現要對i到j的路徑進行操作,有通法,如下:先ACCESS(I);再ACCESS(J)的時候,會發現j往上提的過程中碰到的最後一條路徑會是之前i那條
就先用一道題來做個引子吧: 你有一個N*N的棋盤,每個格子內有一個整數,初始時的時候全部為0,現在需要維護兩種操作:命令參數限制內容1 x y A1<=x,y<=N,A是正整數將格子x,y裡的數字加上A2 x1 y1 x2 y21<=x1<= x2<=N1<=y1<= y2<=N輸出x1 y1 x2
線段樹的功能強大而實用,實現也方便,真是好東西這個題重點其實不是線段樹,是這個模型的轉化,這裡需要用到將lca問題轉化為rmq問題的思想(參考郭華陽大牛論文)好了,進入正題本題是要求你完成樹上的兩種操作,一個是改變一條邊權,還有就是詢問兩點間距離如果只有第二個操作,那就是經典問題,dis(i,j)=d[i]+d[j]-2*d[lca(i,j)],d[i]是i到根的距離那麼考慮第一個操作的話,發現改變了某個邊權,影響到的只有這條邊下面的子樹內的點的d值而在那個歐拉序列裡面,一棵子樹會是連續的一段,
題目大意: 在一些有依賴關係的燈裡(即改了這個,那個也改了),要通過改變若干燈的狀態來從初始狀態達到目標狀態,每個燈最多改變一次,方案總數。分析: 由於每個燈只能改1次,那麼最終的狀態就只與跟這個燈相關的燈的改變情況有關,容易想到設立方程組來對問題求解。至於解方程組,高斯大牛已經幫咱們鋪平了道路了,在此對他表示崇高的敬意。演算法:
直接構造優先隊列,每次取出最小的兩個數相加,直到隊列中只有一個數為止,還是用STL過的題。 注意priority_queue的用法,原型:priority_queue<Type> q;priority_queue<Type,deque<Type>,Comp> q;其中Type是類型,Comp是比較結構體,比較函數是它的括弧重載,比如對int型從小到大排序的Comp結構體如下:struct Comp{bool operator()(const LL&
這道題應該是背包問題裡堪稱經典的問題了,表示剛開始學DP,這類問題也很快弄懂了。題目大意是給你一些分組,每組物品放在一個盒子裡,每組物品都有幾種物品,有自己的價格c和價值v,現在要買一個物品時,要買它對應的盒子,盒子的價格是p,問你花一定的錢最多買到的物品價值是多少。 這類問題要用到兩個數組,dp[0][i]表示i塊錢可以買到的最大價值,dp[1][i]表示考慮到當前盒子時,i塊錢可以買到的最大價值,首先dp[0]置為0,枚舉全部的盒子,dp[1]置為-oo表示買不到,更新的轉移可以從dp[0]
今晚做這題,因為使用int型貢獻了不少的WA,最後改成long
持續一個半月的暑期ACM集訓暫時告一段落,想想也改把平時遇到的問題進行總結了。。在這個暑期的集訓中,我們的能力可以說是發生了質的變化,想想去年剛接觸ACM的時候做的趣味賽,以及前半年參加的校賽,從校初賽5題驚險出線到現在可以和隊友在一起切題,感覺就是一眨眼間的事情。這最後的大半個月,我和兩個隊友基本上每天都做一套題,過題數從剛開始的3、4道到現在的5、6道,可以說我們在成長,整個集訓隊的孩子們都在成長。而在這個過程中,也暴露出了許多的問題,在此,我做出如下總結:1。題目的意思最重要,看題是整場比
許多分類,把這題分到了最短路裡面,也看過一些用Floyd、SPFA的寫法,但是我覺得,這題沒必要想太複雜,直接建立最小產生樹,在建樹的過程中,如果加入了一條邊,使得起點和終點連通了,那麼這條邊一定是最大的那條,也就是答案。 My Code如下,每次加入一條邊,判斷0、1的連通性。 #include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <
這題糾結了好久,之前沒有考慮到flag標記,如果有如下的資料,之前的想法就錯了:1200000000 直接建字典樹,注意一下幾點:1.如果當前的結點是標記了danger的,那麼就直接返回false,表示有首碼。2.如果遍曆到最後依然沒有發現danger標記,要考慮這個結點有沒有後繼,如果有,說明他是某些結點的首碼,這個用flag標記。 自己在代碼裡加了一些注釋,以便理解。My Code: #include <vector>#include <list>#include &
今晚最後一題衝動了,沒看範圍就類比,為某孩子送去了50分。。。好吧,我在這裡說說前兩題。。。 275 求平均數這題對我這個數學不怎麼樣的人來說,第一反應就搜尋了,反正n<=8嘛,O(2^8)暴過。。 My Code:int a[10];int n,cnt;long long sum;void dfs(int k,int num,int cur){if(k==n){if(num==0)return;sum+=cur;cnt+=num;return;}dfs(k+1,num,cur);dfs(
這題被範圍卡了挺久,線段樹的懶操作是指訪問到的指定區間如果在需要求的區間內部,那麼就直接返回,這樣,就遇到了一個問題,就是如何記錄子區間的狀態,用一個del變數來記錄子區間的狀態,注意,是子區間,這樣我們就可以用精簡的代碼來完成更新區間尋找區間的操作。 My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace
本題思路和一般字典樹有所不同,將全部的字串讀入離線處理,insert操作和大部分字典樹一致,接下來就是一個dfs函數,枚舉全部字串是否是合格,dfs的tim參數表示了這個是第幾次查詢,如果遇到danger標記,就可以有兩種路徑,繼續本次查詢和進入下一個查詢,這樣講每一個字串都判斷完畢即可。 My Code:#include <vector>#include <list>#include <map>#include <set>#include
好吧,我承認這題很簡單(不會STL的孩子把這句話無視),看錯題目導致成功掛零。。。無語死了。。。 今天的250不是很難,要點有:1。對字串的切割,手寫切割函數比較保險,當然會用STL的字串流的可以直接按照空格切割。2。尋找關鍵字,嗯,這裡有個好技巧,用紅/黑樹狀結構(set)來維護全部的危險關鍵字即可。3。判斷條件,只有當危險關鍵字超過定值的時候才是危險網站,否則不是。4。當一個網站是危險網站的時候,他的全部關鍵字都是危險的,這時候,我們要把全部的關鍵字加入紅/黑樹狀結構中管理。5。由於4的原因
這題還是一樣的題型,插入和查詢,這次查詢find函數中要注意的就是如果遍曆到一個結點之後對應的next指標為空白,就返回0。用cnt記錄首碼出現次數,這時候就不用danger標記了。 My Code:#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include
這道題有兩個重要的地方,一個是對題目的理解,合法的操作只有一種,那就是對相鄰的兩個狀態不同的燈泡進行交換狀態的操作,也就是說,相鄰的燈泡如果都是亮著的或者暗著的,那麼不能對這條邊進行操作。第二點,那就是由於所有的狀態的目標狀態都是一樣的,那麼我們就可以從目標狀態進行BFS,計算出其他狀態到目標狀態要多少步,注意當BFS的步數大於3的時候,就不要將其子狀態放入隊列中,為了方便,之前將全部的狀態的需要步數設定為5,這樣即使沒有訪問的狀態,步數也是大於3的,這個演算法的時間複雜度是O(32^3),完全
雖然這題用排序可以輕鬆搞定,但是我們可以考慮用二分匹配,在O(n^2)的時間內得到答案。將兩個字串中每個字母的數目進行統計,然後得到一個有26對結點的二分圖,對二分圖跑一次最大匹配,若且唯若最大匹配數等於26的時候,輸出YES,否則輸出NO。 二分版本的代碼,運用匈牙利演算法實現:#include <cstdio>#include <cstring>#include <cstdio>#include <cstdlib>using
這題因為建圖卡了好久,Dancing Links的入門題,不想多說什麼。想瞭解的請參看Knuth的論文。這裡學會了一個很方便的雙向鏈表插入演算法,如果要將x插入到雙向鏈表中,只要先更新x的指標域,然後調用dlx的第二步就可以了。在init函數有所實現。 My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#define
求逆序對的題目,可以用暴力、樹狀數組來實現。 1。暴力法:O(n^2)對於1000的規模完全可以做,直接找第i個元素之後有多少個比其小的元素即可。 代碼:#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;int main(){int t,n,cnt=0;int a[1005];int ret;scanf("%d",&