PTA天梯赛L2

L2-001 紧急救援 

题意:就是给你一张n<500的图;让你求最短路径,最短路条数,以及路径;

做法,先用dijkstra求最短路,然后dfs找最短路条数,以及点权的最大值;

一般dfs不就可以解决这个问题吗,像n皇后求次数,注意回溯即可;

那如何dfs确定这条路是最短路径呢?贪心思想,枚举每一个邻居,如果满足   dis[y.v]==dis[x]+y.w 说明当前邻居 通过这个点可以一直是最短路径,这样dfs下去,如果碰到d就return掉;

主要是没有想到用dfs求最短路径条数,然后注意回溯即可;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e3+5;
int n,m,s,d;
int dis[maxn],val[maxn];
bool vis[maxn];
struct edge{int v,w;edge(int a,int b){v=a,w=b;}};
vector<edge>e[maxn];
struct node{
    int id,dis;
    node(int a,int b){id=a,dis=b;}
    friend bool operator<(node a,node b){
    return a.dis>b.dis;
    }
};
void solve(){
    rep(i,0,n)vis[i]=0,dis[i]=inf;
    dis[s]=0;
    priority_queue<node>Q;
    Q.push(node(s,0));
    while(!Q.empty()){
    node u=Q.top();
    Q.pop();
    if(vis[u.id])continue;
    vis[u.id]=1;
    for(int i=0;i<e[u.id].size();i++){
    edge y=e[u.id][i];
    if(vis[y.v])continue;
    if(dis[y.v]>y.w+u.dis){
    dis[y.v]=y.w+u.dis;
    Q.push(node(y.v,dis[y.v]));
    }    
    }
    }
}
int Max,cnt;
vector<int>path,pre;
void dfs(int x,int w){
    if(x==d){
    if(w>Max){
    Max=w;
    path=pre;
    }
    cnt++;
    return ;
    }
    for(int i=0;i<e[x].size();i++){
    edge y=e[x][i];
    if(!vis[y.v]&&dis[y.v]==dis[x]+y.w){
    vis[y.v]=1;
    pre.pb(y.v);
    dfs(y.v,w+val[y.v]);
    vis[y.v]=0;
    pre.pop_back();
    }
    }

}
int main(){
    scanf("%d %d %d %d",&n,&m,&s,&d);
    rep(i,0,n-1)scanf("%d",&val[i]);
    while(m--){
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
    e[a].pb(edge(b,c));
    e[b].pb(edge(a,c));
    }
    solve();
    cnt=0,Max=-1;
    rep(i,0,n)vis[i]=0;
    dfs(s,val[s]);
    printf("%d %d
",cnt,Max);    
    int len=path.size();
    printf("%d ",s);
    for(int i=0;i<len;i++)
    printf("%d%c",path[i],i==len-1?'
':' ');
    return 0;
}
View Code

L2-002 链表去重

假链表

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
// #define fi first
// #define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e5+5;
struct node{int to,k;}arr[maxn];
vector<int>lis1,lis2;
bool vis[maxn]={0};
int main(){
    int fi,n;
    scanf("%d %d",&fi,&n);
    for(int i=1;i<=n;i++){
    int x,y,z;
    scanf("%d %d %d",&x,&y,&z);
    arr[x].k=y,arr[x].to=z;
    }
    for(int i=fi;i!=-1;i=arr[i].to){
    int x=fabs(arr[i].k);
    if(vis[x])lis2.pb(i);
    else {
    lis1.pb(i);
    vis[x]=1;
    }
    }
    for(int i=0;i<lis1.size();i++){
    int x=lis1[i];
    if(i==lis1.size()-1)printf("%.5d %d -1
",x,arr[x].k);
    else printf("%.5d %d %.5d
",x,arr[x].k,lis1[i+1]);
    
    }
    for(int i=0;i<lis2.size();i++){
    int x=lis2[i];
    if(i==lis2.size()-1)printf("%.5d %d -1
",x,arr[x].k);
    else printf("%.5d %d %.5d
",x,arr[x].k,lis2[i+1]);
    
    }
    return 0;
}
View Code

L2-003 月饼 

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e3+5;
struct node{double v,w,ave;}a[maxn];
bool cmp(node a,node b){return a.ave>b.ave;}
int main(){
    int n,d;
    scanf("%d %d",&n,&d);
    rep(i,1,n)scanf("%lf",&a[i].w);
    rep(i,1,n){
    scanf("%lf",&a[i].v);
    a[i].ave=a[i].v/a[i].w;
    }
    sort(a+1,a+1+n,cmp);
    double ans=0;
    for(int i=1;i<=n;i++){
    if(d>a[i].w)ans+=a[i].v,d-=a[i].w;
    else {
    ans+=a[i].ave*d;
    break;
    }
    }
    printf("%.2lf
",ans);
    return 0;
}
View Code

L2-004 这是二叉搜索树吗?

题意:给你个序列,问你是不是   BST  先序遍历或镜像的结果,是的话,输出后序遍历,

这题不会做,看完题解感觉这题很巧妙;

做法:一个  BST 先序遍历的第一个点,必为根节点,然后先序遍历去找左节点,然后回来,在这个过程中所有点都比根节点小;

    在遍历右节点的时候,所有节点都比根节点大;

所以可以找一个分界线,使得分界线前面的元素都比根小,分界线后面的元素都比根大,那分界线前面的元素必是左子树上的点,分界线后面的元素必然是

右子树上的点,然后递归处理左子树和右子树,最终建成了一颗树,然后回溯时 符合后序遍历的特点,先左后右,再根;

回溯的时候有个问题,就是  root和tail 相等的时候,这时候会再递归一次,return掉以后,把节点记录下来;

确实很巧妙的题;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e3+5;
vector<int>post;
int pre[maxn];
bool ismirror;
void buildtree(int root,int tail){
    int i=root+1;
    int j=tail;
    if(!ismirror){
    while(i<=tail&&pre[i]<pre[root])i++;
    while(j>root&&pre[j]>=pre[root])j--;
    }
    else {
    while(i<=tail&&pre[i]>=pre[root])i++;
    while(j>root&&pre[j]<pre[root])j--;
    }
    if(i-j!=1)return ;
    buildtree(root+1,j);
    buildtree(i,tail);
    post.pb(pre[root]);
}
int main(){
    int n;
    scanf("%d",&n);
    rep(i,1,n)scanf("%d",&pre[i]);
    ismirror=false;
    buildtree(1,n);
    if(post.size()!=n){
    ismirror=true;
    buildtree(1,n);
    }
    if(post.size()!=n)printf("NO
");
    else {
    printf("YES
");
    for(int i=0;i<n;i++)
    printf("%d%c",post[i],i==n-1?'
':' ');
    
    }
    return 0;
}
View Code

L2-005 集合相似度

今天才知道set也可以搞个数组;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e4+5;
set<int>st[60];
int main(){
    int k,n;
    scanf("%d",&n);
    rep(i,1,n){
    int x,m;
    scanf("%d",&m);
    while(m--){
    scanf("%d",&x);
    st[i].insert(x);
    }
    }
    scanf("%d",&k);
    while(k--){
    int a,b;
    scanf("%d %d",&a,&b);
    int tot=st[a].size()+st[b].size();
    set<int>::iterator it;
    int cnt=0;
    for(it=st[a].begin();it!=st[a].end();it++){
    int x=*it;
    if(st[b].find(x)!=st[b].end())cnt++;
    }
    double ans=cnt*1.0/(tot-cnt);
    printf("%.2lf%
",ans*100);
    }
    return 0;
}
View Code

 L2-006 树的遍历

题意:给出后序遍历和中序遍历,让你求层次遍历;这题不会做,看了大神解法;

解法:二叉树遍历有这样的性质:中序遍历的序列:一个节点左边的元素一定是它左子树上的点,同理一个节点右边的元素一定是它右子树上的点;

  后序遍历有这样的特点:最后一个元素,一定是根;

  前序遍历有这样的特点:最前面一个元素,一定是根;

  那根据这个特点,每次从 后序遍历 找出一个根,在由  中序遍历 找他的左右子树元素,递归处理就行了;

  注意边界情况:当只有递归到叶节点后:ra=la,rb=lb;在递归一次,发现ra<la,或者rb<lb     处理为 return 0;

层次遍历广搜即可,这里我开始先遍历右树,后遍历左树,错了一次;应该是先遍历左树,后遍历右树;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e5+5;
int in[50],post[50];
struct tree{int r,l;}trees[maxn];
int n;
int build(int la,int ra,int lb,int rb){
    if(la>ra)return 0;
    int root=post[rb];
    int p1=la;
    while(in[p1]!=root)p1++;
    int dis=p1-la;
    trees[root].l=build(la,p1-1,lb,lb+dis-1);
    trees[root].r=build(p1+1,ra,lb+dis,rb-1);
    return root;
}
void bfs(){
    vector<int>v;
    queue<int>Q;
    Q.push(post[n]);
    while(!Q.empty()){
    int x=Q.front();
    Q.pop();
    // if(x==-1)break;
    v.pb(x);
    if(trees[x].l!=0)Q.push(trees[x].l);
    if(trees[x].r!=0)Q.push(trees[x].r);

    }
    int len=v.size();
    for(int i=0;i<len;i++){
    printf("%d%c",v[i],i==len-1?'
':' ');
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&post[i]);
    for(int i=1;i<=n;i++)scanf("%d",&in[i]);
    build(1,n,1,n);
    bfs();    
    // system("pause");
    return 0;
}
View Code

 L2-008 最长对称子串

暴力即可,注意 对称子串可以是奇数,也可以是偶数,两层枚举即可;

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    getline(cin,s);
    int  maxlen=1;
    int len=s.size();
    for(int i=0;i<len;i++){
    int cnt=0;
    while(i+cnt<len&&i-cnt>=0&&s[i+cnt]==s[i-cnt])cnt++;
    cnt--;
    if(cnt*2+1>maxlen)maxlen=cnt*2+1;
    }
    for(int i=0;i<len;i++){
    int cnt=0;
    while(i+cnt+1<len&&i-cnt>=0&&s[i+cnt+1]==s[i-cnt])cnt++;
    // cnt--;
    if(cnt*2>maxlen)maxlen=cnt*2;
    }
    printf("%d
",maxlen);
        // system("pause");
    return 0;
}
View Code

L2-009 抢红包

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e4+5;
struct node{int cnt,id,tot;}a[maxn];
bool cmp(node a,node b){
    if(a.tot!=b.tot)return a.tot>b.tot;
    else if(a.cnt!=b.cnt)return a.cnt>b.cnt;
    else return a.id<b.id;
}
int n;
void init(){
    for(int i=0;i<=n;i++){
    a[i].tot=a[i].cnt=0,a[i].id=i;
    }
}
int main(){
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++){
    int k;
    int cnt=0;
    scanf("%d",&k);
    while(k--){
    int x,y;
    scanf("%d %d",&x,&y);
    a[x].tot+=y;
    a[x].cnt++;
    cnt+=y;
    }
    a[i].tot-=cnt;
    }

    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
    printf("%d %.2lf
",a[i].id,a[i].tot*1.0/100);
    }

    return 0;

}
View Code

L2-010 排座位

这题和帮派问题的带权并查集不一样,

帮派问题:敌人的敌人是朋友,朋友的敌人是敌人,敌人的朋友是敌人;

食物链那个题:如果同被一类生物吃,或者同吃一类生物,那么他们是同类;

这是带权并查集,有明显的对立关系,

但这个题,敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人,敌人的朋友也不一定是敌人;

所以不用带权并查集,朋友关系是共享的,用并查集关系解决,敌对关系不是共享的,用map数组处理;

因为题目说明了 只有直接的敌对关系才算敌对,而朋友关系是可以共享的;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
#define pb push_back
#define pf push_front
#define fi first
#define se second 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef double db;
const db PI=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int inf=0x3f3f3f3f;//0x7fffffff;
const double eps=1e-9;
const ll MOD=1e9+9;
const int maxn=1e4+5;
int fa[400],MP[400][400];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void build(int x,int y){int dx=find(x),dy=find(y);if(dx!=dy)fa[dx]=dy;}
int main(){

    int n,k,m;
    scanf("%d %d %d",&n,&m,&k);
    // init();
    for(int i=1;i<=2*n;i++)fa[i]=i;
    while(m--){
    int x,y,op;
    scanf("%d %d %d",&x,&y,&op);
    if(op==1)build(x,y);
    else if(op==-1)MP[x][y]=MP[y][x]=-1;
    }
    while(k--){
    int x,y;
    scanf("%d %d",&x,&y);
    bool isfriend=0,isenemy=0;
    if(find(x)==find(y))isfriend=1;
    if( MP[x][y]==-1)isenemy=1;
    if(isfriend&&!isenemy)
    cout<<"No problem"<<endl;
    else if(!isfriend&&!isenemy)
    cout<<"OK"<<endl;
    else if(isfriend&&isenemy)
    cout<<"OK but..."<<endl;
    else if(!isfriend&&isenemy)
    cout<<"No way"<<endl;
    
    }
    return 0;
}
View Code

 L2-011 玩转二叉树 

这个是前面一个题的变化版

就是给你前序和中序,让你求镜像的层次遍历;

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
int pre[50],in[50];
struct tree{int r,l;}trees[50];
int buildtree(int la,int ra,int lb,int rb){
    //la 前序,lb 后序
    if(la>ra)return 0;
    int root=pre[la];
    int p1=lb;
    while(in[p1]!=root)p1++;
    int dis=p1-lb;
    trees[root].l=buildtree(la+1,la+dis,lb,p1-1);
    trees[root].r=buildtree(la+dis+1,ra,p1+1,rb);
    return root;
}
void bfs(){
    vector<int>v;
    queue<int>Q;
    Q.push(pre[1]);
    while(!Q.empty()){
    int x=Q.front();
    Q.pop();
    v.pb(x);
    if(trees[x].r!=0)Q.push(trees[x].r);
    if(trees[x].l!=0)Q.push(trees[x].l);
    }
    int len=v.size();
    for(int i=0;i<len;i++){
    printf("%d%c",v[i],i==len-1?'
':' ');
    }
}
int main(){

    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&in[i]);
    for(int i=1;i<=n;i++)scanf("%d",&pre[i]);
    buildtree(1,n,1,n);
    bfs();
    return 0;
}
View Code

 L2-012 关于堆的判断 ;

这题有这样几个知识点:

堆就是一个完全二叉树,且每个根节点都满足最大或者最小,

建立堆:边读取边调整,每次从下往上调整父节点,最后一定是一个正确的堆,复杂度O(nlog(n));

判断父结点,子节点,什么的,除2就行了;

但这题截取字符串比较麻烦;

我用流处理的;方便一些;

#include<bits/stdc++.h>
using namespace std;
int trees[2000];
void adjust(int x){
    if(x==1)return ;
    if(trees[x]<trees[x/2]){
    swap(trees[x],trees[x/2]);
    adjust(x/2);
    }
}
bool judge1(int a,int b){
    int p1=1,p2=1;
    while(trees[p1]!=a)p1++;
    while(trees[p2]!=b)p2++;
    if(p1/2!=p2/2)return 0;
    return 1;
}
bool judge2(int a,int b){
    int p1=1,p2=1;
    while(trees[p1]!=a)p1++;
    while(trees[p2]!=b)p2++;
    if(p2/2!=p1)return 0;
    return 1;    
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
    scanf("%d",&trees[i]);
    if(i!=1)adjust(i);
    }
    while(m--){
    int a,b;
    string op;
    scanf("%d ",&a);
    getline(cin,op);
    int len=op.size();
    if(op[0]=='i'&&op[len-1]=='t'){
    if(trees[1]!=a)printf("F
");
    else printf("T
");
    }
    else if(op[0]=='a'){
    istringstream in(op);
    string tmp;
    in>>tmp>>b>>tmp>>tmp;
    if(judge1(a,b))printf("T
");
    else printf("F
");
    }
    else if(op[0]=='i'&&op[3]=='t'){
    istringstream in(op);
    string tmp;
    in>>tmp>>tmp>>tmp>>tmp>>b;
    if(judge2(a,b))printf("T
");
    else printf("F
");
    }
    else {
    istringstream in(op);
    string tmp;
    in>>tmp>>tmp>>tmp>>tmp>>b;
    if(judge2(b,a))printf("T
");
    else printf("F
");    
    }
    }

    return 0;
}
View Code

 L2-013 红色警报

这个题折腾了好久;

题意:给你一张连通图,每次删除一个点,问你这个点是不是桥;

做法:本来想用邻接表存图,但你用vector  确实不好删除元素呀,而且每次把他的邻居踢掉,还要把以他为邻居的点踢掉,

这个复杂度就不对了,所以存图的结构看情况而定,

邻接矩阵能很好的描述两两的  邻接关系 ,但邻接表就比较麻烦,要遍历整个vector;

每次踢掉一个点,统计这张图的联通分量,做个判断即可,

然后这里我没有递归处理邻居的邻居,邻居的邻居不还是邻居吗?

我傻傻的不知道递归处理;

但这个题,复杂度真的很高呀;算的复杂度是  1e8  居然过了,真是神奇;

#include<bits/stdc++.h>
using namespace std;
int gp[600][600];
bool vis[600];
int n,m,k;
void dfs(int x){
    vis[x]=1;
    for(int i=0;i<n;i++){
        if(!vis[i]&&gp[x][i]==1)dfs(i);
    }
}
int countcnt(){
    memset(vis,0,sizeof(vis));
    int cnt=0;
    for(int i=0;i<n;i++){
    if(!vis[i]){
    cnt++;
    dfs(i);
    }
    }
    return cnt;
}
int main(){

    memset(gp,0,sizeof gp);
    scanf("%d %d",&n,&m);
    while(m--){
    int a,b;
    scanf("%d %d",&a,&b);
    gp[a][b]=gp[b][a]=1;
    
    }

    scanf("%d",&k);
    int cnt=countcnt();
    for(int i=1;i<=k;i++){
    int x;
    scanf("%d",&x);
    for(int j=0;j<n;j++){
    if(gp[x][j]==1||gp[j][x]==1)gp[x][j]=gp[j][x]=0;
    }
    int tmpcnt=countcnt();
    if(tmpcnt>cnt+1)printf("Red Alert: City %d is lost!
",x);
    else printf("City %d is lost.
",x);
    if(i==n)printf("Game Over.
");
    cnt=tmpcnt;
    }
    return 0;
}
View Code

 L2-014 列车调度;

最开始想的暴力,然后时间复杂度肯定是不对;

傻傻的还想着优先队列,看不到这是个递增的数列吗?

每次选取刚好大于num的数,然后替换掉,咋不知道二分?

STL的三种二分(都是已经排好序的):

binary_search   二分查找一个  左闭右开的区间,有这个元素返回1,否则0;    

lower_bound   二分查找一个 左闭右开的区间   返回值大于或者等于的  最小的   迭代器;  找不到就是 end

upper_bound     二分查找一个 左闭右开的区间   返回值大于该值的   最大的   迭代器  找不到就是 end

以上是从小到大的顺序;

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int maxn=1e5+10;
int a[maxn];
int main(){
        int n;
    scanf("%d",&n);
    vector<int>v;
    vector<int>::iterator it;    
    for(int i=1;i<=n;i++){
    scanf("%d",&a[i]);
    it=upper_bound(v.begin(),v.end(),a[i]);
    if(it!=v.end()) *it=a[i];
    else v.pb(a[i]);
    }
    printf("%d
",v.size());
    return 0;
}
View Code

L2-015 互评成绩

set里是双向迭代器,不能说    it+1

这题就是:你用mulitset是不能直接访问最大值的,要转换一下;每次it++;看看能不能访问end如果是,就退出;

否则回退;

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int maxn=1e5+10;
bool cmp(double a,double b){return a<b;}
int main(){
    vector<double>v;
    int n,k,m;
    scanf("%d %d %d",&n,&k,&m);
    for(int i=1;i<=n;i++){
    multiset<int>st;
    int x;
    for(int j=1;j<=k;j++){
    scanf("%d",&x);
    st.insert(x);
    }
    set<int>::iterator it;
    double sum=0;
    for(it=st.begin();it!=st.end();it++){
    if(it==st.begin())continue;
    it++;
     if(it==st.end()){
        break;
    }
    else it--;
    sum+=*it;
    }
    sum/=k-2;
    v.pb(sum);
    }
    sort(v.begin(),v.end(),cmp);
    for(int i=n-m;i<n;i++){
    printf("%.3lf%c",v[i],i==n-1?'
':' ');
    }

    return 0;
    
}
View Code

 L2-016 愿天下有情人都是失散多年的兄妹 

感觉自己还是太懒了,堕于思考。

题意:让你判断两个人能不能结婚;但数据会卡你,有的人并没有给出性别这种情况;

你如果用bool 标记,那默认值是0,即为默认男性,那就不对了,所以用字符数组标记;

做法,对于一对男女,搜索五代,看看是不是同父或者同母;

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int fa[maxn],mo[maxn];
char sex[maxn];
bool ok(int x,int y,int cnt){
    if(cnt>=5)return 1;
    if(x==-1||y==-1)return 1;
    if(fa[x]!=-1&&fa[y]!=-1&&fa[x]==fa[y])
    return 0;
    if(mo[x]!=-1&&mo[y]!=-1&&mo[x]==mo[y])
    return 0;
    cnt++;
    return ok(fa[x],mo[y],cnt)&&ok(fa[y],mo[x],cnt)&&ok(fa[x],fa[y],cnt)&&ok(mo[x],mo[y],cnt);
}
int main(){    

    for(int i=0;i<maxn;i++)fa[i]=mo[i]=-1;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
    int x,f,m;
    char op;
    scanf("%d %c %d %d",&x,&op,&f,&m);
    sex[x]=op;
    fa[x]=f;
    mo[x]=m;
    if(f!=-1)sex[f]='M';
    if(m!=-1)sex[m]='F';
    }
    int m;
    scanf("%d",&m);
    while(m--){
    int x,y;
    scanf("%d %d",&x,&y);
    int cnt =1;
    if(sex[x]==sex[y])printf("Never Mind
");
    else if(ok(x,y,cnt))printf("Yes
");
    else printf("No
");
    }
    return 0;
}
View Code

L2-017 人以群分

把输入文件搞错了,瞎改了半天bug

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
const int maxn=1e5+5;
ll a[maxn];
int main(){    
    int  n;
    scanf("%d",&n);
    // cout<<n<<endl;
    // rep(i,1,n)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    // cout<<"test :"<<endl;
    // for(int i=1;i<=n;i++)cout<<a[i]<<endl;
    // cout<<"test "<<endl;
    sort(a+1,a+1+n);
    if(n%2==1){
    ll sum1=0,sum2=0;
    rep(i,1,n/2)sum1+=a[i];
    rep(i,n/2+2,n)sum2+=a[i];
    // cout<<"test :"<<sum1<<" "<<sum2<<endl;
    printf("Outgoing #: %d
",n/2+1);
    printf("Introverted #: %d
",n/2);
    printf("Diff = %lld
",sum2-sum1+a[n/2+1]);
    }
    else {
    ll sum1=0,sum2=0;
    rep(i,1,n/2)sum1+=a[i];
    rep(i,n/2+1,n)sum2+=a[i];
    // cout<<"test :"<<sum1<<" "<<sum2<<endl;
    printf("Outgoing #: %d
",n/2);
    printf("Introverted #: %d
",n/2);
    printf("Diff = %lld
",sum2-sum1);

    }
    return 0;
}
View Code

L2-019 悄悄关注 

搞个string类的set就可以过了

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
typedef long long ll;
typedef long double ldb;
const int maxn=1e5+5;
struct peo{string name;ldb cnt;}man[maxn];
int main(){ 
    int n;
    scanf("%d",&n);
    set<string>st,List;
    rep(i,1,n){
    string tmp;
    // cin>>List[i].name;
    cin>>tmp;
    List.insert(tmp);
    }
    int m;
    scanf("%d",&m);
    ldb sum=0;

    rep(i,1,m){
    cin>>man[i].name>>man[i].cnt;
    sum+=man[i].cnt;
    }
    sum/=m;
    rep(i,1,m){

    if(man[i].cnt>sum&&List.find(man[i].name)==List.end())st.insert(man[i].name);
    }
    set<string>::iterator it;
    for(it=st.begin();it!=st.end();it++){
    cout<<*it<<endl;
    }
    if(st.empty())cout<<"Bing Mei You"<<endl;
    return 0;
}
View Code

L2-020 功夫传人 

这个题就是遍历图,深搜可以解决;

就是    printf("%.0llf",ans);  这个式子是会四舍五入的;

你只能转为  longlong

这里  long double

读取:scanf("%Lf",&x);

打出:printf("%Lf",x);

下次让打出整数记得  转为 int

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define pb push_back
typedef double db;
typedef long double ldb;
typedef long long ll;
int n;
ldb r,rootpow,ans;
const int maxn=1e5+5;
vector<int>v[maxn];
int big[maxn];
void dfs(int x,ldb frontpow){
    if(big[x]!=0&&v[x].empty()){
    ans+=frontpow*big[x];
    return;
    }
    for(int i=0;i<v[x].size();i++){
    dfs(v[x][i],frontpow*r);
    }
}
int main(){
    memset(big,0,sizeof big);
    scanf("%d %Lf %Lf",&n,&rootpow,&r);
    r=1-r*1.0/100;
    rep(i,0,n-1){
    int k;
    scanf("%d",&k);
    if(k==0){
    scanf("%d",&big[i]);
    }
    while(k--){
    int x;
    scanf("%d",&x);
    v[i].pb(x);
    }
    }

    ans=0;
    dfs(0,rootpow);
    printf("%lld
",(ll)ans);
    return 0;
}
View Code

L2-021 点赞狂魔

没啥意思;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define pb push_back
typedef long long ll;
typedef long double ldb;
const int maxn=1e5+5;
struct node{string name;int cnt,k;};
vector<node>v;
bool cmp(node a,node b){
    if(a.cnt!=b.cnt)
    return a.cnt>b.cnt;
    else return a.k<b.k;
}
int main(){ 
    int n;
    cin>>n;
    node tmp;
    rep(i,1,n){
    // tmp.cnt=0;
    cin>>tmp.name>>tmp.k;
    // cin>>a[i].name;
    set<int>st;
    int x;
    // scanf("%d",&tmp.k);
    rep(j,1,tmp.k){
    scanf("%d",&x);
    st.insert(x);
    }
    tmp.cnt=st.size();
    v.pb(tmp);
    }
    sort(v.begin(),v.end(),cmp);
    tmp.name="-";
    rep(i,1,3)v.pb(tmp);
    // for(int i=0;i<v.size();i++)
    // cout<<v[i].name<<" "<<v[i].cnt<<endl;
    rep(i,0,2){
    cout<<v[i].name;
    if(i!=2)cout<<" ";
    }
    cout<<endl;
    return 0;

}
View Code

L2-023 图着色问题

没看懂题意就急着写,瞎改bug半天;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(int )j;i<=(int)k;i++)
const int maxn=600;
#define pb push_back
struct edge{int u,v;edge(int x,int y){u=x,v=y;}};
vector<edge>e;
int color[maxn];
int V,E,K;
bool ok(){
    for(int i=0;i<e.size();i++){
    if(color[e[i].u]==color[e[i].v])return 0;
    }
    return 1;
}
int main(){

    int n,x,y;
    scanf("%d %d %d",&V,&E,&K);
    rep(i,1,E){
    scanf("%d %d",&x,&y);
    e.pb(edge(x,y));
    }
    scanf("%d",&n);
    rep(k,1,n){
    set<int>st;
    int flag=1;
    rep(i,1,V){
    scanf("%d",&color[i]);
    if(color[i]>V||color[i]<=0)flag=0;
    st.insert(color[i]);
    }
    if(st.size()!=K||!flag)printf("No
");
    else if(ok())printf("Yes
");
    else printf("No
");
    
    }
    return 0;
}
View Code
想的太多,做的太少;
原文地址:https://www.cnblogs.com/littlerita/p/12346776.html