CF1620 E. Replace the Numbers (1900)(启发式合并)

https://codeforces.com/problemset/problem/1620/E
题意: 初始为空的数组,有两种操作:1 :在后面加一个数x 2:把所有的x改成y。 n和x,y的范围都在5e5内。

  • 对于所有的x改成y这个操作,给每个数字设一个id,然后修改id这样是不行的,因为后面新加的数也会受id影响。 不如暴力一点:把x的位置们全部扔给y。这个复杂度可以用启发式合并来保证。
  • map的first值无法修改,所以搞一个id[]数组来实现修改first操作。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, int>
const int N = 5e5 + 5;
const int M = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);

int id[N], ans[N];
int main () {
   IOS
   map<int, vector<int>> mp;
   int q; cin >> q;
   int opt, x, y; int idx = 0, pos = 0;
   while( q -- ) {
       cin >> opt;
       if(opt == 1) {
           cin >> x;
           if(id[x]) mp[id[x]].push_back(++ pos);
           else {
               id[x] = ++ idx;
               mp[id[x]].push_back(++ pos);
           }
       } else {
           cin >> x >> y;
           if(!id[x] || !mp[id[x]].size() || x == y) continue;
           if(!id[y]) id[y] = ++idx;

           if( mp[id[x]].size() < mp[id[y]].size() ) {
               for ( auto j : mp[id[x]]) {
                   mp[id[y]].push_back(j);
               }
               mp[id[x]].clear();
           } else {
               for ( auto j : mp[id[y]]) {
                   mp[id[x]].push_back(j);
               }
               mp[id[y]].clear();
               swap(id[x], id[y]);
           }
       }
   }
   for ( int i = 1; i <= 500000; ++ i ) {
       if( !id[i] || mp[id[i]].empty() ) continue;
       for ( auto j : mp[id[i]]) {
           ans[j] = i;
       }
   }
   for ( int i = 1; i <= pos; ++ i ) {
       cout << ans[i] << " ";
   }
   cout << '\n';
   return 0;
}
posted @ 2022-04-11 20:33  qingyanng  阅读(29)  评论(0编辑  收藏  举报