3 条题解
-
1
这个代码翻译过来就是,有个数,每个数有一种颜色,次操作把颜色替换成,求每次替换后同种颜色最近点对。
然后这个替换颜色就是很板的启发式合并。
考虑统计答案,发现答案不增,所以每次启发式合并插入的时候计算答案,和原来的答案取即可。
用可以做到单次,启发式合并,总复杂度>
不用启发式合并看起来有,数据水成啥了..
#include<bits/stdc++.h> using namespace std; //#define int long long int n,m; int a[101000]; int X[101000],Y[101000]; int b[301000],btt; int EF(int x){ int l=1,r=btt; while(l<r){ int mid=((l+r)>>1); if(b[mid]>=x) r=mid; else l=mid+1; }return l; } int lst[301000]; int col[301000],fcol[301000]; int sz[301000]; set<int>setz[301000],setf[301000]; int st[301000],top; signed main(){ // freopen("ex.in","r",stdin); // freopen("my.out","w",stdout); // system("fc my.out ex.out");return 0; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; b[++btt]=a[i]; } for(int i=1;i<=m;i++){ cin>>X[i]>>Y[i]; b[++btt]=X[i];b[++btt]=Y[i]; } sort(b+1,b+btt+1); btt=unique(b+1,b+btt+1)-b-1; int ans=2147483647; for(int i=1;i<=n;i++){ a[i]=EF(a[i]); if(lst[a[i]]) ans=min(ans,i-lst[a[i]]); lst[a[i]]=i; sz[a[i]]++; setz[a[i]].insert(i); setf[a[i]].insert(-i); } for(int i=1;i<=btt;i++) col[i]=fcol[i]=i; for(int i=1;i<=m;i++){ X[i]=EF(X[i]); Y[i]=EF(Y[i]); int cx=fcol[X[i]],cy=fcol[Y[i]]; if(sz[cx]>sz[cy]){ swap(fcol[X[i]],fcol[Y[i]]); swap(col[cx],col[cy]); swap(cx,cy); } if(cx==cy){ cout<<ans<<"\n"; continue; } sz[cy]+=sz[cx];sz[cx]=0; for(auto x:setz[cx]){ if(setz[cy].lower_bound(x)!=setz[cy].end()){ ans=min(ans,abs(*setz[cy].lower_bound(x)-x)); } if(setf[cy].lower_bound(-x)!=setf[cy].end()){ ans=min(ans,abs(*setf[cy].lower_bound(-x)+x)); } setz[cy].insert(x); setf[cy].insert(-x); st[++top]=x; } while(top){ setz[cx].erase(st[top]); setf[cx].erase(-st[top]); top--; } cout<<ans<<"\n"; } return 0; } -
0
#include <bits/stdc++.h> using namespace std; map<int, set<int>>mp; int ans = 2147483647; void dis(int id, int x){ // 更新答案 auto it = mp[id].lower_bound(x); if(it != mp[id].end()) ans = min(ans, *it - x); if(it != mp[id].begin()) --it, ans = min(ans, x - *it); } void solve() { int n, m; scanf("%d%d", &n, &m); for (int i = 1 ; i <= n ; i ++) { int x; scanf("%d", &x); dis(x, i); mp[x].insert(i); } while(m--) { int x, y; scanf("%d%d", &x, &y); if (x == y) printf("%d\n", ans); else { if (mp[x].size() > mp[y].size()) swap(mp[x], mp[y]); for (auto it : mp[x]) { // 启发式合并, 小的往大的上面并 dis(y, it); mp[y].insert(it); } mp[x].clear(); printf("%d\n", ans); } } } int main() { solve(); return 0; }
- 1
信息
- ID
- 770
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 47
- 已通过
- 6
- 上传者