CF 977 Review

Hanggoash發表於2024-10-06

CF 977 Review

掉大分了,我去,綠名也是可以掉分的,我去你簡直太牛了sgh。

我是真正的飛舞。

A

排序以後貪心或者直接優先佇列模擬即可,都可以過。

Code

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
} 
template<typename T>inline void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar(x%10^48);
}
int n,m,k;
int main()
{
	int T;
	re(T);
	priority_queue<int,vector<int>,greater<int>> q;
	while(T--)
	{
		re(n);
		int tmp;
		for(register int i=1;i<=n;++i)re(tmp),q.push(tmp);
		for(register int i=1;i<=n-1;++i)
		{
			int x=q.top();q.pop();
			int y=q.top();q.pop();
			q.push((x+y)/2);
		}
		wr(q.top()),putchar('\n');
		q.pop();
	}
	return 0;
}

B

分析

給定一個序列 \({a_n}\)\(x>0\) ,可以任意次數的將序列中的任意一個數加上 \(x\) ,求在最優操作下序列 mex 的最大值。

需要明確的是我們一定是要儘可能地讓較小的數都能夠存在。

因為只能執行加的操作 ,所以達成這一目的一定是要把 多餘的 並且 更小的 數進行操作得到的。

那麼我們只需要把序列sort一遍然後模擬即可,注意一遍模擬一遍檢查是否出現答案,還要記錄當前數字的個數。

複雜度 \(O(n\log n)\) 可以透過。

Code

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
} 
template<typename T>inline void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar(x%10^48);
}
int n,x;
int a[200010]; 
int main()
{
	int T;
	re(T);
	while(T--)
	{
		set<int> s;unordered_map<int,int> CNT;
		re(n),re(x);
		for(register int i=1;i<=n;++i)re(a[i]);
		sort(a+1,a+n+1);
		int cnt=1;
		a[n+1]=-1;
		for(register int i=1;i<=n;++i)
		{
			if(a[i]==a[i+1])
				cnt++;
			else 
			{
				s.insert(a[i]);
				CNT[a[i]]=cnt;
				cnt=1;
			}
		}
		int las=-1;
		for(auto it:s)
		{
			if(it-las>=2){wr(las+1),putchar('\n');goto A;}
			if(CNT[it]>1)
			{
				if(!s.count(it+x))s.insert(it+x); 
				CNT[it+x]+=CNT[it]-1;
			}
			las=it;
		}
		wr(las+1),putchar('\n');
		A:continue;
	}
	return 0;
}
/*
1
6 1
1 3 4 1 0 2
*/

C(easy)

題意不多贅述,因為太難贅述了。

分析

先看一組樣例 :

a:1 2 3 4

b:1 2 3 4   2 3 4 1   2 3 1 4

你會發現只要前四個能夠匹配上,好像後面一定能夠滿足。

那如果我後面八個再寫雜亂無章一點,比如 2 1 3 2 1 4 1 2 ,會發現無論怎麼寫都一定能夠滿足。

那如果我再寫的極限一點:

a:1 2 3 4

b:1 2 3     2 3 4 1  2 3 1 4

這下好像仍然可以,但前四個就不一定一樣了。

看看樣例裡面不合法的一個情況呢?

a:3 1 4 2 5
b:3 1 4 5 2 3 4

這下前三個相同,但是又不合法了,說明和前幾位相同實際上沒有什麼必要的關係。

多舉幾組反例會發現,b 裡面的數字必須按照 a 中的順序出現,言下之意,當 \(a_i\) 沒有第一次出現的時候,\(a_{i+1}\) 就不能先出現,因為此時就不可以透過操作使 \(a_{i+1}\) 出現在 \(a_i\) 前面。

根據以上分析,我們只需要記錄每個 \(a_i\) 第一次出現的位置即可。或者說直接按位匹配,不合法就直接輸出。

(寫的時候差臨門一腳了,還是自己太笨了,腦子轉的不夠快)

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
} 
template<typename T>inline void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar(x%10^48);
}
int n,m,q;
const int N=2e5+10;
int a[N],b[N],c[N];
inline void solve()
{
	re(n),re(m),re(q);
	for(register int i=1;i<=n;++i)re(a[i]);
	for(register int i=1;i<=m;++i)re(b[i]);
	int cnt=0;b[m+1]=0;
	for(register int i=1;i<=m;++i)
	{
		if(b[i]==b[i+1])continue;
		c[++cnt]=b[i];
	}
	vector<int> vis(n+10,0);
	for(register int i=1,p=1;i<=cnt;++i)
	{
		if(c[i]==a[p])vis[a[p++]]=1;
		else if(!vis[c[i]])
		{
			puts("TIDAK");
			return ;
		}
	}
	puts("YA");
}
int main()
{
	int T;
	re(T);
	while(T--)
		solve();
	return 0;
}

(去重並不是必要的)

C(hard)

挖個坑

D

這個太難了暫時不補了

E

挖個坑