题意:给一群男女匹配,数据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; }
题意:求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(); } }
就是在判断三点位置关系的时候,必须要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
原文:https://www.cnblogs.com/littlerita/p/12640056.html