The 2019 China Collegiate Programming Contest Harbin Site-----E、Exchanging Gifts
题意:
有n个序列\(S_{i}\)。
有n行的输入,有两种操作可以得到\(S_{i}\)。
1、 1 m \(s_{i1}\) \(s_{i2}\) …… \(s_{im}\) 。
2、 2 x y 表示这个数组由 第x和y的数组合并产生。
问:最后得到的数组\(S_{n}\),在经过重新排列后,最多可以有几个元素和原本的\(S_{n}\)不同。
思路:
首先我们看最后需要的答案,很显然,在重新排列后,如果这个数组中出现次数最多的元素的出现次数比原数组的长度的一半小,则答案就是原数组的长度。否则,答案就是(数组长度 - 重复次数)*2。
方法1:
我们需要看每个已知的数组对最终数组的贡献次数,就可以得到最终数组。要求贡献次数,直接从n~1枚举数组的贡献。在知道贡献次数以后,我们可以便利所有需要用到的数组,然后用map记录所有元素的个数。最后就可以求出最终数组中的元素总量和出现次数最多的数字的出现次数。既可求出答案(复杂度大于O(n),较慢)
方法2:
在求每个数组的贡献次数时,直接从n~1枚举数组的贡献,用一个O(n)求众数的方法求出数组中出现次数最多的元素的出现次数即可。(O(n))。
此题最好用快读,否则容易tle。
代码:
方法1:
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long
#define MOD 1000000007
#define pdd pair<double,double>
#define mem(a,x) memset(a,x,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3fLL;
const int inf = 0x3f3f3f3f;
const double eps=1e-6;
const int maxn=1000005;
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(int &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int flag[maxn],in[maxn];
bool vis[maxn];
ll cnt[maxn];
int n,m;
vector<int>co[maxn];
vector<int>G[maxn];
map<int,ll>ans;
queue<int>q;
int op[maxn][3];
void init()
{
for(int i=1;i<=n;i++){
co[i].clear();
G[i].clear();
vis[i]=in[i]=cnt[i]=0;
if(!q.empty())q.pop();
}
ans.clear();
}
void gao()
{
for(int i=n;i>=1;i--){
if(flag[i]==2){
cnt[op[i][1]]+=cnt[i];
cnt[op[i][2]]+=cnt[i];
}
}
for(int i=1;i<=n;i++){
if(cnt[i]!=0&&flag[i]==1){
for(auto j:co[i]){
ans[j]+=cnt[i];
}
}
}
ll sum=0,maxx=0;
for(auto &i:ans){
sum+=i.second;
if(i.second>maxx)maxx=i.second;
}
if(maxx*2>=sum){
printf("%lld\n",(sum-maxx)*2);
}else{
printf("%lld\n",sum);
}
}
int main()
{
int T;
IO;
read(T);
while(T--){
read(n);
init();
for(int i=1;i<=n;i++){
read(flag[i]);
if(flag[i]==1){
read(m);
for(int j=1;j<=m;j++){
int x;
read(x);
co[i].push_back(x);
}
}else{
read(op[i][1]);
read(op[i][2]);
}
}
cnt[n]=1;
gao();
}
return 0;
}
方法2:
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long
#define MOD 1000000007
#define pdd pair<double,double>
#define mem(a,x) memset(a,x,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3fLL;
const int inf = 0x3f3f3f3f;
const double eps=1e-6;
const int maxn=1000005;
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(int &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int n,m;
vector<int>co[maxn];
ll cnt[maxn];
int flag[maxn];
int op[maxn][3];
void solve()
{
cnt[n]=1;
for(int i=n;i>=1;i--){
if(flag[i]==2){
cnt[op[i][1]]+=cnt[i];
cnt[op[i][2]]+=cnt[i];
}
}
//
ll tot=0,val=0;
ll all=0;
for(int i=1;i<=n;i++){
if(flag[i]==1&&cnt[i]>0){
for(auto x:co[i]){
if(val==0){
tot+=cnt[i];
val=x;
continue;
}else if(val==x){
tot+=cnt[i];
}else{
tot-=cnt[i];
if(tot<0){
tot=-tot;
val=x;
}
}
}
all+=co[i].size()*cnt[i];
}
}
tot=0;
for(int i=1;i<=n;i++){
if(cnt[i]>0&&flag[i]==1){
for(auto v:co[i]){
if(v==val)tot+=cnt[i];
}
}
}
//cout<<"aa"<<all<<" "<<tot<<endl;
if(tot*2>=all){
cout<<(all-tot)*2<<endl;
}else{
cout<<all<<endl;
}
}
int main()
{
IO;
int T;
read(T);
while(T--){
read(n);
for(int i=1;i<=n;i++){
co[i].clear();
cnt[i]=0;
read(flag[i]);
if(flag[i]==1){
read(m);
for(int j=1;j<=m;j++){
int x;
read(x);
co[i].push_back(x);
}
}else{
read(op[i][1]);
read(op[i][2]);
}
}
solve();
}
return 0;
}
越自律,越自由