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\n",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

猜你喜欢

转载自www.cnblogs.com/littlerita/p/12640056.html