2019ICPC(徐州) - so easy(并查集+离散化)
題目鏈接:點擊查看
題目大意:給出一個1~n的序列,然后給出m個操作,每個操作分為下列兩種情況:
題目分析:因為n給到了1e9,而查詢只有1e6,所以我們必須將數據離散化,我最初的思路是先將1e6個查詢記錄下來,將操作1使用過的數字放到一個有序數列中,離線處理,可以倒著一步步模擬,每次遇到操作1就將其刪除(即加入回原數組中),然后二分查找第一個大于等于它本身的數,我讓隊友模擬的,最后果然這個題目卡了stl的時間,TLE了,然后我就想用vector模擬鏈表寫一下這個題,經過隊友的提醒,發現了這就是一個離散化后的并查集,但我不太會寫,就先用vector正向模擬的這個題目,最后還是以TLE告終,臨比賽結束前半個小時終于有了最終的思路,就是在離散化的時候,將涉及到的x和x+1同時加入到并查集中,這樣正向遍歷一遍詢問,每次遇到刪除就將當前節點的父節點改為下個節點的父節點,遇到詢問就直接輸出該節點的父節點即可
不過還是需要注意一下離散化后的id和并查集的對應關系,寫那一部分的時候一定要細心想一下,不能對應錯
還有個細節需要注意一下,因為每次push進去的是點x和點x+1,所以最壞情況會有2e6個點,所以數組要開2e6,開1e6會RE
題解是說用map并查集維護一條鏈表,不過不能用普通的map,會超時,要用unordered_map,據說是O1的查詢
補充一下map和unordered_map的區別吧:
map:
map內部實現了一個紅黑樹,該結構具有自動排序的功能,因此map內部的所有元素都是有序的,紅黑樹的每一個節點都代表著map的一個元素,因此,對于map進行的查找,刪除,添加等一系列的操作都相當于是對紅黑樹進行這樣的操作,故紅黑樹的效率決定了map的效率。?
unordered_map:
unordered_map內部實現了一個哈希表,因此其元素的排列順序是雜亂的,無序的
其他方法都是一樣的用法
蒟蒻的代碼:(又臭又長但條理還挺清晰的-.-)
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e6+100;vector<int>v;int fa[N];int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]); }struct Node {int op,x; }q[N];int getid(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin(); }int main() { // freopen("input.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)!=EOF){v.clear();for(int i=1;i<=m;i++){scanf("%d%d",&q[i].op,&q[i].x);v.push_back(q[i].x);v.push_back(q[i].x+1);}v.push_back(n);sort(v.begin(),v.end());//離散化+去重v.erase(unique(v.begin(),v.end()),v.end());for(int i=0;i<v.size();i++)fa[i]=i;for(int i=1;i<=m;i++){int op=q[i].op;int x=q[i].x;int id=getid(x);if(op==1){fa[id]=find(id+1);}else{printf("%d\n",v[find(id)]);}}}return 0; }題解的代碼:順便偷學了一波unordered_map
#include <bits/stdc++.h>using namespace std; const int maxn = 1e5 + 100; unordered_map<int, int> fa;int findfa(int x) {if (!fa.count(x)) return x;return fa[x] = findfa(fa[x]); }int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout);int n, q;scanf("%d %d", &n, &q);int op, x;while (q--) {scanf("%d %d", &op, &x);if (op == 1) {fa[x] = findfa(x + 1);} else {int ans = findfa(x);if (ans > n) ans = -1;printf("%d\n", ans);}}return 0; }?
總結
以上是生活随笔為你收集整理的2019ICPC(徐州) - so easy(并查集+离散化)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019ICPC(徐州) - Who i
- 下一篇: 2019ICPC(南昌) - The N