CF 977 Review
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
挖个坑
本文来自博客园,作者:Hanggoash,转载请注明原文链接:https://www.cnblogs.com/Hanggoash/p/18449226