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
挖個坑