C:二分匹配使得至多的行列要求相同最多在同一个位置
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
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 yr) 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&&vymx) mx=val,Mid=i;
}
ans=max(ans,mx);
if(!Mid){
if(a[mid].y=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
#include
#include
#include
#include
#include
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;i0) return 1;
return 0;
}
int main(){
while(cin>>n>>m){
for(int i=0;i1e-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
#include
#include
#include
#include
#include
#include
using namespace std;
const int mx=30;
int n,m;
bool vis[mx][mx],vit[mx];
vector vec[mx];
void dfs(int x,int fa){
for(int i=0;i>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