C:二分匹配使得至多的行列要求相同最多在同一个位置
#include<iostream>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
const int mx=110;
int n,m;
int fron[mx],side[mx],map[mx][mx],cp[mx];
bool vis[mx],vic[mx][mx];
bool Pipei(int x){
for(int i=1;i<=m;i++){
if(!vis[i]&&vic[x][i]){
vis[i]=1;
if(!cp[i]||Pipei(cp[i])){
cp[i]=x;
return 1;
}
}
}
return 0;
}
int main(){
while(cin>>n>>m){
memset(fron,0,sizeof(fron));
memset(side,0,sizeof(side));
memset(cp,0,sizeof(cp));
memset(vic,0,sizeof(vic));
ll sum=0,sub=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",map[i]+j);
side[i]=max(side[i],map[i][j]);
fron[j]=max(fron[j],map[i][j]);
sum+=map[i][j];
if(map[i][j]) sub++;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
if(map[i][j]&&side[i]==fron[j])
vic[i][j]=1;
}
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
Pipei(i);
}
for(int i=1;i<=n;i++)
if(side[i]) sub+=side[i]-1;
for(int i=1;i<=m;i++)
if(!cp[i]&&fron[i]) sub+=fron[i]-1;
printf("%lld\n",sum-sub);
}
return 0;
}
D:
问题即给出两个点集 AA 与 BB ,分别从中各选取一个点 (xa,ya),(xa,ya), (xb,yb)(xb,yb) ,满足 xa≤xbxa≤xb ,最大化 (xb−xa)(yb−ya)(xb−xa)(yb−ya) ,答案与 00 取最大值。
注意到 AA 中每个点在 BB 中对应的选择只会是坐标均不小于它的点,如果 AA 中存在两个点 P,QP,Q 满足 PP 的坐标均不小于 QQ ,那么 PP 不会对最大值产生贡献,可以移除,BB 同理。
剔除没有贡献的点后,两个点集中的点均可以排序成横坐标递增且纵坐标递减的点列,考虑 AA 中每个点在 BB 中每个点的匹配并将其连边,通过交换论证可以发现,这些匹配边只会在端点处相交,也即决策单调(对于决策不存在的情况也适用)。于是随便分治一下就可以了。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
const int mx=5e5+10;
typedef long long ll;
using namespace std;
int n,m,px,py,vx[mx];
ll ans;
struct point{
ll x,y;
bool operator < (point A)const{
if(x==A.x) return y<A.y;
return x<A.x;
}
}a[mx],wb[mx],b[mx];
void CDQ(int l,int r,int L,int R){
if(l>r) return ;
int mid=(l+r)>>1,Mid=0;
ll mx=0,vy=a[mid].y;
for(int i=upper_bound(vx+L,vx+R+1,a[mid].x)-vx;i<=R&&vy<b[i].y;i++){
ll val=(b[i].x-a[mid].x)*(b[i].y-a[mid].y);
if(val>mx) mx=val,Mid=i;
}
ans=max(ans,mx);
if(!Mid){
if(a[mid].y<b[L].y) CDQ(l,mid-1,L,R);
if(a[mid].x<b[R].x) CDQ(mid+1,r,L,R);
}else{
CDQ(l,mid-1,L,Mid);
CDQ(mid+1,r,Mid,R);
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].y);
for(int i=1;i<=m;i++) scanf("%lld%lld",&wb[i].x,&wb[i].y);
sort(a+1,a+1+n);
sort(wb+1,wb+1+m);
px=py=1,b[1]=wb[m];
for(int i=2;i<=n;i++)
if(a[i].y<a[px].y) a[++px]=a[i];
for(int i=m-1;i>=1;i--)
if(wb[i].y>b[py].y) b[++py]=wb[i];
reverse(b+1,b+1+py);
for(int i=1;i<=py;i++) vx[i]=b[i].x;
ans=0,CDQ(1,px,1,py);
printf("%lld\n",ans);
}
}
E:二分求解就行了,这题水题吧。
#include<iostream>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
const int mx=1e3+10;
int n,m;
struct node{
double d,s;
}po[mx];
int check(double x){
double t=0;
for(int i=0;i<n;i++){
if(po[i].s+x<=0) return 0;
t+=po[i].d/(po[i].s+x);
}
if(fabs(m-t)<1e-6) return 2;
if(m-t>0) return 1;
return 0;
}
int main(){
while(cin>>n>>m){
for(int i=0;i<n;i++) scanf("%lf%lf",&po[i].d,&po[i].s);
double l=-2000.000001,r=1e9,mid;
while(r-l>1e-6){
mid=(l+r)/2;
int val=check(mid);
if(val==2) break;
else if(val==1) r=mid;
else l=mid;
}
printf("%.7lf\n",mid);
}
return 0;
}
I:预处理标记str[i]到stc[i]是否可以转换。就可以了
#include<iostream>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
const int mx=30;
int n,m;
bool vis[mx][mx],vit[mx];
vector <int> vec[mx];
void dfs(int x,int fa){
for(int i=0;i<vec[x].size();i++){
int son=vec[x][i];
if(vit[son]) continue;
vis[fa][son]=1;
vit[son]=1;
dfs(son,fa);
}
}
int main(){
while(cin>>n>>m){
char a,b;
for(int i=0;i<26;i++) vec[i].clear();
memset(vis,0,sizeof(vis));
while(n--){
cin>>a>>b;
vec[a-'a'].push_back(b-'a');
}
for(int i=0;i<26;i++){
memset(vit,0,sizeof(vit));
vis[i][i]=1,vit[i]=1;
dfs(i,i);
}
char str[110],stc[110];
while(m--){
scanf("%s%s",str,stc);
int flag=0,lenr=strlen(str),lenc=strlen(stc);
if(lenr!=lenc) { puts("no"); continue; }
if(strcmp(str,stc)==0) { puts("yes"); continue; }
for(int i=0;i<lenr;i++){
int p=str[i]-'a',t=stc[i]-'a';
if(!vis[p][t]){ flag=1; break; }
}
puts( flag? "no":"yes");
}
}
return 0;
}