文章目录
写在前面
div2一如既往打的很烂·····,赛时C题经常都是卡着,每次都是赛后才写出来,还是得多刷div2的题目······
A. Make All Equal
思路
签到题,找出最大值的个数,总数减去最大值个数即可
code
void solve(){
map<int,int> m;
int maxn=0;
int n;cin >> n;
for(int i=1;i<=n;++i){
int x;cin >> x;
m[x]++;
maxn=max(maxn,m[x]);
}
cout << n-maxn << endl;
return ;
}
B. Generate Permutation
思路
考点:模拟+构造
假设排列是升序的,那么正序只需要操作一次,倒序就需要操作n次
那么正序和倒序所需要的操作数就为
n
+
1
n+1
n+1 次
我们需要做的就是让正序和倒序操作数相同,很明显当n为偶数时,他们一定不可能实现
一个很明显的构造:先找出序列的中位数,将左右两边的数进行调换,调换完左边的数是倒着的,右边的数是正着的
好比一个序列1 2 3 4 5 6 7
颠倒完后为:7 6 5 1 2 3 4
正反的操作数都为4次
code
void solve(){
int n;cin >> n;
if(n==1){
cout << 1 << endl;
return ;
}
if(n%2==0) cout << -1 << endl;
else{
for(int i=n;i>n/2+1;--i) cout << i << " ";
for(int i=1;i<=n/2+1;++i) cout << i << " ";
cout << endl;
}
return ;
}
C. Guess The Tree
思路
对于每次询问,它都会有两种情况:
- 程序给出的答案为 a a a
- 程序给出的答案不为 a a a
对于第一种情况,显然我们已经找到了答案,直接将他们存到
a
n
s
ans
ans数组即可
对于第二种情况,我们可以让
a
a
a不断更新为程序给出的整数
x
x
x,直到程序给出的值为
a
a
a停止,将当前这两个数存入ans数组
code
void solve(){
map<PII,int> m;
int n;cin >> n;
for(int i=2;i<=n;++i){
int a=1,b=i;
while(a!=b){
cout << "? " << a << " " << b << endl;
int x;cin >> x;
if(x==a) break;
a=x;
}
m[{a,b}]=1;
}
cout << "! " ;
for(auto i : m){
PII pa=i.fi;
cout << pa.fi << " " << pa.se << " ";
}
cout << endl;
return ;
}
D. Longest Max Min Subsequence
思路
考点:贪心
我们先不考虑-1的情况,就看这个序列最长的长度
显然,它最长的长度就为序列中不重复元素的总和
既然它要在奇数项的位置乘上-1,那么奇数项上的元素越大,乘完之后就越小
对于偶数项而言,自然是越小越好
从贪心的思想去考虑,每次奇数项都放最大值,偶数项都放最小值即可
我们可以开两个大根堆去维护每次取值的范围,最大值的根堆存的是正值,最小值的根堆存的是负值
每次取值都判断当前元素是否被取过以及当前的坐标是否比上一次取值的坐标大即可
code
const int N=1e6+5;
int a[N],ans[N],vis[N];
void solve(){
unordered_map<int,int> m;
priority_queue<PII> mx,mn;
set<int> s;
int n;cin >> n;
for(int i=1;i<=n;++i){
cin >> a[i];
m[a[i]]++;
}
for(int i=1;i<=n;++i) vis[i]=0;
int len=m.size();
int cnt=1,pos=0;
for(int i=1;i<=n;++i){
m[a[i]]--;
mn.push({-a[i],-i});
mx.push({a[i],-i});
if(m[a[i]]==0){
while(!vis[a[i]]){
if(cnt & 1){
while (mx.size() && (vis[mx.top().first] || -mx.top().second <= pos)) mx.pop();
if (mx.size()) {
ans[cnt++]=mx.top().first;
vis[mx.top().first]=1;
pos =-mx.top().second;
mx.pop();
}
}
else{
while (mn.size() && (vis[-mn.top().first] || -mn.top().second <= pos)) mn.pop();
if (mn.size()) {
ans[cnt++]=(-mn.top().first);
vis[-mn.top().first]=1;
pos = -mn.top().second;
mn.pop();
}
}
}
}
}
cout << len << endl;
for(int i=1;i<=len;++i) cout << ans[i] << " ";
cout << endl;
return ;
}