昨天鸽了一天 导致今天还没补完前面的四道题 明天大概会补上(吧
整体难度:简单(这套卷肯定是12月的)
时间:2小时10分钟(第四个题非逼自己用不熟悉动态树,其实本来四个题都属于简单类型的,这个时间用的过多)
- PAT 1112 找出卡顿键
题目大意:现在键盘有若干卡顿键,如果遇到卡顿则会重复输出n次,给出一段字符串,找出卡顿键。
思路:遍历字符串,找出每个字符连续出现的所有次数(这里数据量不大,放肆地所以用map<char,vector < int > >都完全足够) 注意细节的地方是最后一个字符或者第一个字符的次数可能会落掉一次,我第一次没有考虑到,导致两个点没有过。
代码:
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <iostream>
using namespace std;
const int maxn=10010;
map< char,vector<int> > m;
vector<char> ans;
string str;
bool Hash[1000];
bool cmp(char a,char b){
int x,y;
for(int i=0;i<str.size();i++){
if(str[i]==a) {x=i;break;}
}
for(int i=0;i<str.size();i++){
if(str[i]==b) {y=i;break;}
}
return x<y;
}
int n;
int main(){
cin>>n>>str;
int temp=1;
for(int i=1;i<str.size();i++){
if(str[i-1]==str[i]){temp++;}
else{
m[str[i-1]].push_back(temp);
temp=1;
}
}
if(str[str.size()-1]!=str[str.size()-2]) m[str[str.size()-1]].push_back(1);
else m[str[str.size()-1]].push_back(temp);
for(auto it=m.begin();it!=m.end();it++){
bool flag=false;
//cout<<it->first<<" ";
for(int i=0;i<it->second.size();i++){
//cout<<it->second[i]<<" ";
if(it->second[i]%n!=0){flag=true;}
}
//cout<<endl;
if(flag==false) {ans.push_back(it->first);Hash[it->first]=true;}
}
sort(ans.begin(),ans.end(),cmp);
for(int i=0;i<ans.size();i++) cout<<ans[i]; cout<<endl;
for(int i=0;i<str.size();i++){
cout<<str[i];
if(Hash[str[i]]==true){i+=n-1;}
}
cout<<endl;
return 0;
}
- PAT1113 分组
题目大意:给一个数组,分成两组,使得元素个数差最小,元素合差最大。
思路:最水25分题, 连long long都没让用可见是多么希望你ac。
代码:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=10010;
vector<int> num;
int N,a,b;
int main(){
scanf("%d",&N);
for(int i=0;i<N;i++){
int temp;scanf("%d",&temp);
num.push_back(temp);
}
sort(num.begin(),num.end());
for(int i=0;i<N/2;i++){a+=num[i];}
for(int i=N/2;i<N;i++){b+=num[i];}
if(N%2==0) cout<<0;else cout<<1;
cout<<" "<<b-a;
}
- PAT1114 家族房产信息
题目大意:给出n家的户口本(雾) 记录着 户主 父母 孩子的编号,和房产数量与总面积,求一共出现了多少家族,平均的房产和面积是多少。
思路:典型并查集,这里要注意union处需要稍微魔改一些,永远使得小的节点作为合并后的父亲节点即可。 这里最好开两个结构体,一个记录每个人的房产信息,一个记录家族信息,这样比较便于理解。还有就是注意之前的错误:合并union函数是寻找父节点后,两个父节点进行合并,原因已经在前面说明。
代码:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
const int maxn=10010;
int father[maxn];
int N;
struct Peo{
int id,num,area;
}peo[maxn];
struct Fam{
int id,peonum,setnum,sum;
}fam[maxn];
bool cmp(Fam a,Fam b){
if(a.peonum*b.peonum==0) return a.peonum>b.peonum;
if(1.0*a.sum/a.peonum!=1.0*b.sum/b.peonum) return 1.0*a.sum/a.peonum>1.0*b.sum/b.peonum;
else return a.id<b.id;
}
void re(){for(int i=0;i<maxn;i++) {father[i]=i;}}
int find(int x){
int a=x;
while(x!=father[x]){
x=father[x];
}
while(a!=x){
int s=a[father];
a[father]=x;
a=s;
}
return x;
}
void Union(int a,int b){
int A=find(a);
int B=find(b);
if(A<B) father[B]=A;
if(B<A) father[A]=B;
}
bool visit[maxn];
int main(){
cin>>N;re();
for(int i=0;i<N;i++){
int per,fa,mo;
scanf("%d%d%d",&per,&fa,&mo);
visit[per]=true;
if(fa!=-1) {Union(per,fa);visit[fa]=true;}
if(mo!=-1) {Union(per,mo);visit[mo]=true;}
int size;scanf("%d",&size);
for(int i=0;i<size;i++){
int temp;scanf("%d",&temp);
visit[temp]=true;
Union(temp,per);
}
peo[per].id=per;
scanf("%d%d",&peo[per].num,&peo[per].area);
}
int ans=0;
for(int i=0;i<maxn;i++){
if(visit[i]!=true) continue;
int fa=find(i);
if(fam[fa].peonum==0) ans++;
fam[fa].id=fa;
fam[fa].peonum++;
fam[fa].setnum+=peo[i].num;
fam[fa].sum+=peo[i].area;
}
sort(fam,fam+maxn,cmp);
cout<<ans<<endl;
for(int i=0;i<ans;i++){
printf("%04d %d %.3lf %.3lf\n",fam[i].id,fam[i].peonum,fam[i].setnum*1.0/fam[i].peonum,fam[i].sum*1.0/fam[i].peonum);
}
}
- PAT1115 查找树的节点
题目大意:给出一个二叉查找树,找出最后两层的个数。
思路:先建树(其实静态动态都可以,不过想练一练动态树,结果翻车。)然后遍历赋层值,然后遍历查找符合条件的节点。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=1010;
int N;
struct Node{
int data,layer;
Node* left;
Node* right;
};
void insert(Node* &root,int now){
//cout<<now<<endl;
if(root->data<now){
//cout<<" 1"<<endl;
if(root->right==NULL){
Node *Now;
Now= new Node;
Now->data=now;
Now->left=NULL;Now->right=NULL;
root->right=Now;
}
else insert((root->right),now);
}
if(root->data>=now){
//cout<<" 2"<<endl;
if(root->left==NULL){
Node *Now;
Now= new Node;
Now->data=now;
Now->left=NULL;Now->right=NULL;
root->left=Now;
}
else insert((root->left),now);
}
return;
}
int maxlayer=0;
void getlayer(Node* &root,int layer){
root->layer=layer;
maxlayer=max(layer,maxlayer);
if(root->left!=NULL) getlayer(root->left,layer+1);
if(root->right!=NULL) getlayer(root->right,layer+1);
}
int a=0,b=0;
void getnum(Node* &root){
if(root->layer==maxlayer) a++;
if(root->layer==maxlayer-1) b++;
if(root->left!=NULL) getnum(root->left);
if(root->right!=NULL) getnum(root->right);
}
int main(){
cin>>N;
int root;
scanf("%d",&root);
Node* node = NULL;
node = new Node;
node->data = root;node->left = NULL;node->right = NULL;
for(int i=1;i<N;i++){
int temp;
scanf("%d",&temp);
//cout<<" "<<temp<<endl;
insert(node,temp);
}
//while(now!=NULL) {cout<<now->data<<" ";now=now->left;};
getlayer(node,1);
getnum(node);
printf("%d + %d = %d",a,b,a+b);
}
关于动态树的各种函数,会单独开一个坑记录 这里注意的是因为动态树记录是地址,由于姓名资源是有限的,(总不能给每个节点用字符串的方式单独附一个名字吧),因此最长用的使用指向这个树的指针,而建立指针后需要用 new 函数开辟空间,同时所有的的变量都是没有初始化的,都需要自行初始化,这一点要特别注意。