zoukankan      html  css  js  c++  java
  • 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
    想的太多,做的太少;
  • 相关阅读:
    gcc编译器创建和使用静态库、动态库
    shared_ptr & unique_ptr & weak_ptr (C++11)
    MyString(重写String)
    Linux进程间通讯的几种方式的特点和优缺点,和适用场合
    按行N等分某个文件
    Hbase region 某个regionserver挂掉后的处理
    gentoo
    Hbase 常用shell命令
    网络爬虫速成指南(二)网页解析(基于算法)
    hbase 0.96 java 示例
  • 原文地址:https://www.cnblogs.com/littlerita/p/12346776.html
Copyright © 2011-2022 走看看