(年前年后的一块一起写了)(一些比较有意思的题在这里写一下)
Problem - B - Codeforces
题意
将一个长n的数组按顺序分成k个不为空的子数组,将所有第偶数个子数组合成一个数组并且在末尾加一个0,第一个数序号为1,定义此数组的代价为最小的 满足序号为i的数不等于i 的 i
输出最小的代价
思路
用贪心,希望第二的子数组的第一个数不是1,此时的代价就为1,为最小值
那如果前面有数为1,那么就划给第一个数组,注意第一个数组的最大长度为n-k+1
但实际上要求第二的数组的第一个数不为1就行,所以遍历前 n-k+1+1 个数来判断
如果前 n-k+1+1 个数都为1,此时分两种情况
第一种: n==k 此时每个数为一个子数组,取偶数位的数组成新数组按题意遍历找到满足要求的数就行
第二种: n>k 此时至少前三个数为1 ,将第一个1给第一个子数组,第二、第三个1 给第二个子数组,此时偶数数组的第二个数为1(不等于2)满足题意,代价为2,为当前情况下的最小值
(别走,看吐槽)
吐槽
注意特判前n-k+1+1个数中非1 的数是否只有一个并且是第一个数,如果是这种情况,按前 n-k+1+1 个数都为1 来处理,因为第一个子数组也不能为空
AC代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k;
int arr[200005];
int cha;
void solve(){
int ans = 1e9+9;
cin>>n>>k;
cha = n-k+1;
for(int i=1;i<=n;++i) cin>>arr[i];
for(int i=n+1;i<=n+2;++i) arr[i]=0;
for(int i=1;i<=cha+1;++i){
if(arr[i]!=1 && i!=1){
ans = min(ans,(long long)1);
break;
}
}
if(ans != 1){
if(cha+1>=3){
ans = min(ans,(long long)2);
}
}
if(ans > 2){
for(int i=2;i<=n+2;i+=2){
if(arr[i]!=(i>>1)){
ans = min(ans,(i>>1));
}
}
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}
PTA - 千手观音
题意
给出一些按升序排列的以字符串表示单个数字的数,求每个字符串(数)间的大小关系,无明确关系的按字典序顺序输出
思路
很明显是一个拓扑排序,同一层中的用一个优先队列来存就能实现按字典序输出
但拓扑排序的图怎么建出来呢?
这里我们明确一个大前提:
我们只能明确 两个位数相同且已知大小关系的的数中 从高位到低位 第一个不相同的数的大小关系
例如:
若 aa.ab.cc>aa.ac.bb 我们只能明确ab>ac
在这个大前提下对输入建图,我们就能进行拓扑排序得到答案了
吐槽
优先队列记得开成小根
AC代码
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n;
string s;
vector<string> now,before;
unordered_map<string,vector<string> > adjacency_list;
priority_queue<string,vector<string>,greater<string> > pq;
unordered_map<string,int> indegree;
queue<string> ans;
vector<string> cut(string s){
vector<string> res;
string ss;
for(int i=0;i<s.size();++i){
if(s[i]!='.') ss+=s[i];
else{
res.push_back(ss);
if(!indegree.count(ss)) indegree[ss]=0;
ss.clear();
}
}
if(!ss.empty()){
res.push_back(ss);
if(!indegree.count(ss)) indegree[ss]=0;
ss.clear();
}
return res;
}
void solve(){
cin>>n;
cin>>s;
before=cut(s);
for(int i=1;i<n;++i){ //cout<<i;
cin>>s;
now = cut(s);
if(before.size() == now.size()){
for(int j=0;j<now.size();++j){
if(before[j] != now[j]){
adjacency_list[before[j]].push_back(now[j]);
++indegree[now[j]];
break;
}
}
}
before = now;
}//邻接表建图↑
//拓扑排序↓
for(auto xx:indegree){
if(xx.second==0) pq.push(xx.first);
} //cout<<pq.size();
while(!pq.empty()){
s = pq.top();
pq.pop();
ans.push(s);
for(auto xx:adjacency_list[s]){
--indegree[xx];
if(indegree[xx]==0) pq.push(xx);
}
} //cout<<ans.size();
while(!ans.empty()){
if(ans.size()==1){
cout<<ans.front();
return;
}
cout<<ans.front()<<".";
ans.pop();
}
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}