• 2020年4月4日训练


    A - Thanks, TuSimple!

     ZOJ - 4090 

    题意:给一群男女匹配,数据1e5;

    解法:怎么想?不要看什么匹配都是匈牙利匹配。匈牙利建图都是n*n的,而且匈牙利匹配的边是没有特异性的,和谁匹配都一样效果

    而这题可以贪心取边。和谁匹配是有差别的,应该让差值尽可能小的一起匹配,这样才是最优的,

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    #define pb push_back
    int a[N],b[N];
    vector<int>v1,v2,v3,v4;
    int main(){
        int t;scanf("%d",&t);
        while(t--){
        int p,n,m;scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=m;i++)scanf("%d",&b[i]);
        v1.clear();v2.clear();v3.clear();v4.clear();
        for(int i=1;i<=n;i++){
        scanf("%d",&p);
        if(p)v1.pb(a[i]);
        else v2.pb(a[i]);
        }
        for(int i=1;i<=m;i++){
        scanf("%d",&p);
        if(p)v3.pb(b[i]);
        else v4.pb(b[i]);
        }
        sort(v1.begin(),v1.end());
        sort(v4.begin(),v4.end());
        sort(v3.begin(),v3.end());
        sort(v2.begin(),v2.end());    
        int ans=0;
        for(int i=0,j=0;i<v1.size()&&j<v4.size();){
            if(v1[i]<v4[j]){ans++;i++;j++;}
            else j++;
        }
        for(int i=0,j=0;i<v2.size()&&j<v3.size();){
            if(v2[i]>v3[j]){ans++;i++;j++;}
            else i++;
        }
        printf("%d
    ",ans);
        }
        // system("pause");
        return 0;
    }
    View Code

    B - Even Number Theory

     ZOJ - 4091 

    题意:求2*4*6*8*...n的2因子数
    拓展为1*2*3*4*5*6*7...n
    然后每次/2,获取因子数,累积结果

    import java.util.*;
    import java.math.BigInteger;
    
    
    public class Main {
           public static void main(String[] args) {
               Scanner in=new Scanner(System.in);
               int T;
               T=in.nextInt();
               BigInteger n;
               while(T-->0) {
                   BigInteger ans;
                   ans=BigInteger.valueOf(0);
                   n=in.nextBigInteger();
                   while(n.compareTo(BigInteger.valueOf(0))>0) {
                       n=n.divide(BigInteger.valueOf(2));
                       ans=ans.add(n);
                   }
                   System.out.println(ans);
               }
               in.close();
           }
           
    }
    View Code

    G - Rescue the Princess

     ZOJ - 4097 

    就是在判断三点位置关系的时候,必须要log(n)解决。公主的位置必然在两个骑士中间。
    考虑如何在树上解决三点关系:有自环和重边时没法建树,于是把每一个边双联通压成一个点,
    这样把自环和重边解决了,讨论三点在边双联通的位置关系:
    1,三者都在一个边双联通,yes
    2,公主与任意一个在一个边双联通,yes
    3.两个骑士在一个边双联通,公主在另一个边双联通,no
    4 三个人在三个边双联通,分类讨论。公主的位置必然在两个骑士中间。

     但是要注意:有自环和重边,处理回退边

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    const int M=18;
    #define pb push_back
    int n,m,cnt,dfn,BCC;
    int bcc[N],low[N],num[N],dep[N],fa[N],head[N];
    bool vis[N];
    int dp[N][30];
    struct edge{int v,next;}e[N*10];
    void add(int u,int v){
    e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt++;
    }
    vector<int>gp[N];
    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;}
    void init(){
        cnt=dfn=BCC=0;
        for(int i=1;i<=n;i++)
        gp[i].clear(),vis[i]=0,bcc[i]=0,fa[i]=i,low[i]=dep[i]=num[i]=0;
        memset(head,-1,sizeof head);
        memset(dp,0,sizeof dp);
    }
    void tarjan(int u,int tot,int id){
        low[u]=num[u]=++dfn;bcc[u]=tot;
        for(int i=head[u];~i;i=e[i].next){
        if(i==(id^1))continue;
        int v=e[i].v;
        // if(v==father)continue;
        if(!num[v]){
        tarjan(v,tot,i);
        low[u]=min(low[u],low[v]);
        if(low[v]<=num[u])build(u,v);
        }
        else if(num[v]<num[u])low[u]=min(low[u],num[v]);
        }
    }
    void dfs(int u,int dpe){
        dep[u]=dpe;vis[u]=1;
        for(int i=1;i<M;i++)dp[u][i]=dp[ dp[u][i-1] ][i-1];
        for(int i=0;i<gp[u].size();i++){
        int v=gp[u][i];
        if(!vis[v])dp[v][0]=u,dfs(v,dpe+1);
        }
    }
    int  LCA(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        for(int i=M-1;i>=0;i--){
        if(dep[x]-dep[y]>=(1<<i))x=dp[x][i];
        }
        if(x==y)return x;
        for(int i=M-1;i>=0;i--){
        if(dp[x][i]!=dp[y][i])
        x=dp[x][i],y=dp[y][i];
        }
        return dp[x][0];
    }
    int main(){
        int t,q;
        scanf("%d",&t);
        while(t--){
            scanf("%d %d %d",&n,&m,&q);
            init();
        for(int i=1,u,v;i<=m;i++){
            scanf("%d %d",&u,&v);
            add(u,v);add(v,u);
        }
        for(int i=1;i<=n;i++)if(!num[i])tarjan(i,++BCC,-1);
        for(int i=0;i<cnt;i+=2){
        int u=find(e[i].v),v=find(e[i+1].v);
        if(u!=v)gp[u].pb(v),gp[v].pb(u);
        }
        for(int i=1;i<=n;i++){
            int u=find(i);
            if(!vis[u])dfs(u,1);
        }
        for(int i=1,u,v,w;i<=q;i++){
            scanf("%d %d %d",&u,&v,&w);
        if(bcc[u]!=bcc[v]||bcc[u]!=bcc[w]){puts("No");continue;}
    
        u=find(u),v=find(v),w=find(w);
        
        if(u==v||u==w){puts("Yes");continue;}
        
        if(v==w){puts("No");continue;}
        
        int a= LCA(u,v) ,b= LCA(u,w) ,c=LCA(v,w) ;
        
        int Max=a;if(dep[b]>dep[Max])Max=b;if(dep[c]>dep[Max])Max=c;
        
        if(Max==u){puts("Yes");continue;}
        else {puts("No");continue;}
        }
    
        }
        // system("pause");
        return 0;
    }
    
    // 2
    // 6 7 4
    // 1 2
    // 2 3
    // 3 1
    // 4 5
    // 5 6
    // 6 4
    // 1 4
    // 4 1 3
    // 1 4 2
    // 1 2 3
    // 1 3 3
    // 2 1 2
    // 1 2
    // 1 1 1
    // 2 1 2
    View Code

    F - Postman

     ZOJ - 4096 

    F:就是说邮递员送快递,每次只能派送k个物品,如何取最短距离?
    解法:贪心选边,将最远的点最后派送,使得不回头的点最优,然后轮番取边,即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+10;
    int t,n,k;
    ll a[maxn];
    int main(){
        scanf("%d",&t);
        while (t--){
            a[0] = 0;
            scanf("%d%d",&n,&k);
            for (int i = 1; i <= n; i++){
                scanf("%lld",&a[i]);
            }
            sort(a,a+n+1);
            int l = 0, r = n, flag = 1;
            ll ans = 0;
            int zpos = lower_bound(a,a+n+1,0) - a;
            while (l != zpos || r != zpos){
                ll L = abs(a[l]), R = abs(a[r]);
                if (L > R){
                    if (flag) ans += L,flag = 0;
                        else ans += L * 2;
                    if (zpos - l >= k) {
                        l += k;
                    }
                    else{    
                        l = zpos;
                    }
                }
                else{
                    if (flag) ans += R,flag = 0;
                        else ans += R * 2;
                    if (r - zpos >= k){
                        r -= k;
                    }
                    else{
                        r = zpos;
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    H - Extended Twin Composite Number

     ZOJ - 4099 

    简单规律题:

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    typedef long double ldb;
    typedef double db;
    const double eps=1e-8;
    const int N=1e5+5;
    int n,m;
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){ 
        ll n;
        scanf("%lld",&n);
        if(n==1)printf("8 9
    ");
        else printf("%lld %lld
    ",n*2ll,n*3ll);
    
        }
    
    
    
    
      // system("pause");
        return 0;
    }
    View Code
    想的太多,做的太少;
  • 相关阅读:
    mkdir,rmdir
    linux目录结构
    echo
    date
    man
    cd
    ls
    线程、进程
    php类型的自动转换
    电商
  • 原文地址:https://www.cnblogs.com/littlerita/p/12640056.html
Copyright © 2020-2023  润新知