Codeforces Round #733 (Div. 1 + Div. 2, based on VK Cup 2021 - Elimination (Engine)) D. Secret Santa (构造,STL)
-
题意:一共有\(n\)个人,每个人都要送礼物给别人,每个人都要收到礼物,但每个人都有自己相送的人,序列\(a\)表示第\(i\)个人想送礼物给\(a[i]\),输出长度为\(n\)的序列,表示\(i\)送礼物给\(b[i]\).
-
题解:先用set将能给礼物的先给了,即将没收到礼物的\(a[i]\)先给了,给过就erase掉,并且记录答案和送他礼物的人\(i\)(后面有用).然后遍历所有人,如果这个人还没送,就取\(t\)中最靠前的人给他送掉,如果当前最靠前元素恰好是\(i\),如果\(t\)中元素不止一个就取第二靠前的元素,如果只剩一个,说明此时的\(i=n\),\(t\)中的元素也一定是\(n\),前面一定有一个\(a[j]=a[n]\),因为如果只有一个\(a[n]\)话,说明这个位置一定是合法的即我们之前就记录过了,所以\(a[n]\)一定出现了多次,这样我们记录的\(pos\)就派上用场了,直接和任意一个交换位置即可.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int _; cin>>_; while(_--){ int n; cin>>n; vector<int> a(n+1); set<int> s,t; vector<int> pos(n+1); rep(i,1,n){ cin>>a[i]; s.insert(a[i]); t.insert(i); } cout<<(int)s.size()<<'\n'; vector<int> ans(n+1); rep(i,1,n){ if(s.count(a[i])){ ans[i]=a[i]; s.erase(a[i]); t.erase(a[i]); pos[a[i]]=i; } } rep(i,1,n){ if(ans[i]==0){ auto it=t.begin(); int x=*it; t.erase(x); if(x==i){ if(t.empty()){ ans[pos[a[i]]]=x; ans[i]=a[i]; pos[a[i]]=i; } else{ auto itt=t.begin(); int xx=*itt; ans[i]=xx; t.erase(xx); t.insert(x); } } else{ ans[i]=x; } } } rep(i,1,n) cout<<ans[i]<<' '; cout<<'\n'; } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮