2017 World Final專題
阿新 • • 發佈:2019-02-20
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:
問題即給出兩個點集 A 與 B ,分別從中各選取一個點 (xa,ya), (xb,yb) ,滿足 xa≤xb ,最大化 (xb−xa)(yb−ya) ,答案與 0 取最大值。
注意到 A 中每個點在 B 中對應的選擇只會是座標均不小於它的點,如果 A 中存在兩個點 P,Q 滿足 P 的座標均不小於 Q ,那麼 P 不會對最大值產生貢獻,可以移除,B 同理。
剔除沒有貢獻的點後,兩個點集中的點均可以排序成橫座標遞增且縱座標遞減的點列,考慮 A 中每個點在 B 中每個點的匹配並將其連邊,通過交換論證可以發現,這些匹配邊只會在端點處相交,也即決策單調(對於決策不存在的情況也適用)。於是隨便分治一下就可以了。
程式碼:
#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;
}