2020.9.6 20:00-22:00
5道编程题,500分
给定两个长度分别为n,m的链表,1<=n,m<=1000,000, 输出两个链表的公共部分
#include
using namespace std;
const int N = 1e6+100;
int a[N],b[N];
int main(void) {
int n,m;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",a+i);
scanf("%d",&m);
for(int i=0;i<m;++i)
scanf("%d",b+i);
int i = 0, j = 0;
while(i<n&&j<m) {
if(a[i]==b[j]) printf("%d ",a[i]),++i,++j;
else if(a[i]<b[j]) ++j;
else ++i;
}
printf("\n");
return 0;
}
100%
有n个人,有m个小组,每个小组有ki个人。一个人可以属于多个小组,也可以不属于任何一个小组。一个消息,初始0号知道,然后同一小组的人相互告知,求最后多少人知道?包括0。n<=1E5
#include
using namespace std;
const int N = 1e6+10;
int pre[N];
void init() {
for(int i=0;i<N;++i) pre[i] = i;
}
int Find(int x) {
return x==pre[x]?x:pre[x] = Find(pre[x]);
}
void join(int x,int y) {
int fx = Find(x), fy = Find(y);
if(fx!=fy) pre[fy] = fx;
}
int main(void) {
int n,m,x,y;
scanf("%d%d",&n,&m);
init();
set<int> st;
for(int i=1;i<=m;++i) {
scanf("%d",&x);
vector<int> v;
for(int j=0;j<x;++j)
scanf("%d",&y),v.push_back(y),st.insert(y);
for(int i=1;i<x;++i) join(v[i],v[i-1]);
}
int par = Find(0);
int ans = 0;
for(auto it:st) {
if(Find(it)==par) ++ans;
}
printf("%d\n",ans);
return 0;
}
100%
给定n个字符串和一个K, 每个字符串记录出现的次数,输出前K个字符串和后K个字符串。输出2*K行, 前K行,按第一关键字为出现次数从大到小,第二关键字为字典序从小到大。后K行,按第一关键字为出现次数从小到大,第二关键字为字典序从小到大输出。
#include
#include
using namespace std;
map<string,int> mp;
struct Node{
string str;
int cnt;
bool operator < (const Node& rhs)const{
return cnt==rhs.cnt?str<rhs.str:cnt>rhs.cnt;
}
Node(string _str,int _cnt) {
str = _str; cnt = _cnt;
}
};
bool cmp(const Node& a,const Node& b) {
return a.cnt==b.cnt?a.str<b.str:a.cnt<b.cnt;
}
int main(void) {
int n,k;
ios::sync_with_stdio(false);
scanf("%d%d",&n,&k);
string s;
for(int i=1;i<=n;++i) {
cin>>s;
++mp[s];
}
vector<Node> v;
for(auto it:mp) {
v.push_back(Node(it.first,it.second));
}
sort(v.begin(),v.end());
for(int i=0;i<k;++i) {
cout<<v[i].str<<" "<<v[i].cnt<<"\n";
}
sort(v.begin(),v.end(),cmp);
for(int i=0;i<k;++i) {
cout<<v[i].str<<" "<<v[i].cnt<<"\n";
}
return 0;
}
100%
给一个序列,长度为n,n<=200,000。求删除每个数之后,序列的中位数。保证n为偶数。
#include
using namespace std;
const int N = 2e5+100;
pair<int,int> a[N];
int ans[N];
int main(void) {
int n;
scanf("%d",&n);
for(int i=0;i<n;++i) {
a[i].second = i;
scanf("%d",&a[i].first);
}
sort(a,a+n);
int tot = n-1;
int mid = tot/2;
for(int i=0;i<n;++i) { //删除第i个数
if(i<=mid) ans[a[i].second] = a[mid+1].first;
else ans[a[i].second] = a[mid].first;
}
for(int i=0;i<n;++i)
printf("%d\n",ans[i]);
return 0;
}
100%
有一个长度为2*n的格子,上面放了n个红棋子和n个黑棋子
n = 3
BRRBRB
先输入n,然后输入长度为2n的字符串
然后下面是2n个数,第i个数,代表第i个位置的棋子在颜色相同的棋子中的序号
你每次操作可以 交换两个相邻的棋子。
现在要使得相同颜色的棋子,从左到右序号递增
问最少要多少次交换?
3
BRRBRB
2 3 1 1 2 3
#include
using namespace std;
const int N = 3000+100;
/*
题目表述:有一个长度为2*n的格子,上面放了n个红棋子和n个黑棋子
n = 3
BRRBRB
先输入n,然后输入长度为2*n的字符串
然后下面是2*n个数,第i个数,代表第i个位置的棋子在颜色相同的棋子中的序号
你每次操作可以 交换两个相邻的棋子。
现在要使得相同颜色的棋子,从左到右序号递增
问最少要多少次交换?
*/
int a[N*2];
char s[N*2];
struct Node{
int val; //值的大小 or 类型 'R' 'B'
int pos; //原始位置 第几小
Node(int v=0,int p=0){
val = v; pos = p;
}
bool operator < (Node& rhs)const{
return val < rhs.val;
}
};
int p[N*2];
Node r[N*2]; //记录棋盘的现状
int posR[N]; //记录R的第x小的位置
int posB[N]; //记录B的第x小的位置
int len;
void show() {
static int cont = 0;
printf("第%d次交换:\n",cont++);
for(int j=1;j<=len;++j)
cout<<(char)r[j].val;cout<<endl;
for(int j=1;j<=len;++j) cout<<r[j].pos<<" ";cout<<endl<<endl;
}
int main(void) {
int n;
// freopen("in.txt","r",stdin);
scanf("%d",&n);
scanf("%s",s+1);
len = 2*n;
for(int i=1;i<=len;++i)
scanf("%d",p+i);
for(int i=1;i<=len;++i) {
if(s[i]=='R') {
r[i].val = 'R'; //记录类型
r[i].pos = p[i]; //记录第几小
posR[p[i]] = i; //记录B的第p[i]小在位置i
}
else { //s[i]=='B'
r[i].val = 'B'; //记录类型
r[i].pos = p[i];//记录第几小
posB[p[i]] = i; //记录B的第p[i]小在位置i
}
}
int ans = 0;
for(int i=n;i>1;--i) { //先处理R
int rightest_pos = -1;
for(int j=0;j<i;++j) {
if(posR[j]>posR[i]) {
rightest_pos = max(rightest_pos,posR[j]);
}
}
if(rightest_pos==-1) continue;
ans += rightest_pos-posR[i];
Node Ri_tmp = r[posR[i]]; //记录的是R的第i大的类型和第几大
for(int j=posR[i];j<rightest_pos;++j) {
r[rightest_pos] = Ri_tmp;
posR[Ri_tmp.pos] = rightest_pos;
}
//再处理B
for(int i=n;i>1 ;--i) {
int rightest_pos = -1;
for(int j=0;j<i;++j) {
if(posB[j]>posB[i]) {
rightest_pos = max(rightest_pos,posB[j]);
}
}
if(rightest_pos==-1) continue;
ans += rightest_pos-posB[i];
Node Ri_tmp = r[posB[i]];
for(int j=posB[i];j<rightest_pos;++j) {
r[j] = r[j+1];
if(r[j].val=='R') posR[r[j].pos] = j; //更新位置
else posB[r[j].pos] = j;
}
r[rightest_pos] = Ri_tmp;
posB[Ri_tmp.pos] = rightest_pos;
}
cout<<ans<<endl;
return 0;
}
2020.9.7
6:56