T1 矩形
这是一道防AK题(确信)反正我被防了(是个辣鸡)
vanvan没想到还能斜着放,我说第一题怎么能这么简单
很巧妙的方法就是将一个矩形的对角线放在另一个矩形中再判断高度差即可
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
int n;
double a1,a2,b1,b2;
int main(){
cin>>n;
for(int i=1;i<=n;++i){
scanf("%lf%lf%lf%lf",&a1,&b1,&a2,&b2);
if(a1>b1) swap(a1,b1);
if(a2>b2) swap(a2,b2);
if(a1*b1>a2*b2) swap(a1,a2),swap(b1,b2);
if(a1<=a2&&b1<=b2){puts("Yes");continue;}
else{
double r1=a1*a1+b1*b1,r2=a2*a2+b2*b2;
if(r1>r2){puts("No");continue;}
else{
r1=sqrt(r1-b2*b2);
double p=(2.0*b2*a1*b1+b1*b1*r1-a1*a1*r1)/(a1*a1+b1*b1);
if(p-a2<eps) puts("Yes");
else puts("No");
}
}
}
return 0;
}
T2 最短路
首先删边不好想,反向加边即可。
既然删边操作不会超过200次,那么完全可以接受每插入一条边就更新所有以修改点为中转点的路径,复杂度O(n^3)
(差点打挂Floyd)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=210;
const int MAXM=1e5+10;
const int INF=0x3f3f3f3f;
int n,m,now;
int ma[MAXN][MAXN],ans[MAXM],top;
int dis[MAXN][MAXN],ban[MAXN][MAXN];
struct Q{
int type;
int x,y;
}query[MAXM];
int Read(){
int i=0,f=1;
char c=getchar();
for(;(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-') f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int main(){
n=Read(),m=Read();
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
ma[i][j]=Read();
}
}
for(int i=1;i<=m;++i){
query[i].type=Read(),query[i].x=Read(),query[i].y=Read();
if(query[i].type==1) ban[query[i].x][query[i].y]=1;
}
memset(dis,INF,sizeof(dis));
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j) if(!ban[i][j]) dis[i][j]=min(dis[i][j],ma[i][j]);
}
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(dis[i][k]+dis[k][j]<dis[i][j]) dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
for(int i=m;i;--i){
if(query[i].type==2) ans[++top]=(dis[query[i].x][query[i].y])==INF?-1:dis[query[i].x][query[i].y];
else{
if(ma[query[i].x][query[i].y]>=dis[query[i].x][query[i].y]) continue;
dis[query[i].x][query[i].y]=ma[query[i].x][query[i].y];
for(int j=1;j<=n;++j){
for(int k=1;k<=n;++k){
if(dis[query[i].x][j]+dis[j][k]<dis[query[i].x][k]) dis[query[i].x][k]=dis[query[i].x][j]+dis[j][k];
}
}
for(int j=1;j<=n;++j){
for(int k=1;k<=n;++k){
if(dis[j][query[i].x]+dis[query[i].x][k]<dis[j][k]) dis[j][k]=dis[j][query[i].x]+dis[query[i].x][k];
}
}
}
// solve(query[i].x,query[i].y);
}
for(int i=top;i;--i) cout<<ans[i]<<'\n';
}
T3 集合
好像有树形DP的优秀O(n)做法?我太菜了不会啊
首先易证两个集合点一定有一个在直径上,那么我们可以直接二分距离,从直径两端向中间跳二分出的mid个,然后检查两个集合点之间的点到最近集合点加上非直径最长链长度是否不大于二分出的距离即可
dfs本机爆栈于是愉快的写了bfs
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
const int MAXM=4e5+10;
int n,cnt;
int maxx,s,t,ss,tt;
int head[MAXN],vis[MAXN],viss[MAXN],on[MAXN],maxlen[MAXN],dis[MAXN];
int nxt[MAXM],to[MAXM],w[MAXM];
int que[MAXN],id[MAXN],tot;
int Read(){
int i=0,f=1;
char c=getchar();
for(;(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-') f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void add(int x,int y){
nxt[++cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
}
void bfs1(int st){
queue<int> q;
q.push(st);
viss[st]=1;
while(!q.empty()){
int u=q.front();
// cout<<u<<' '<<dis[u]<<'\n';
q.pop();
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(viss[v]) continue;
dis[v]=dis[u]+1;
q.push(v),viss[v]=1;
}
}
// puts("");
}
void bfs2(int st){
queue<int> q;
q.push(st);
while(!q.empty()){
int u=q.front();
// cout<<u<<' ';
q.pop();
vis[u]=1,que[++tot]=u;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(dis[v]!=dis[u]-1||vis[v]) continue;
q.push(v);
}
}
// puts("");
}
int dfs3(int u,int f){
int ret=0;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(v==f||vis[v]) continue;
ret=max(ret,dfs3(v,u)+1);
}
return ret;
}
void findmax(){for(int i=1;i<=tot;++i) maxlen[que[i]]=dfs3(que[i],-1);}
bool check(int x){
for(int i=x+1;i<=tot-x;++i){
// if(x==1){
// cout<<que[i]<<':';
// cout<<maxlen[que[i]]<<' '<<dis[que[i]]<<'\n';
// }
if(maxlen[que[i]]+min(abs(dis[que[i]]-dis[que[x+1]]),abs(dis[que[i]]-dis[que[tot-x]]))>x) return 0;
}
return 1;
}
void find(){
int l=1,r=maxx,mid,ans;
while(l<=r){
mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
}
int main(){
memset(head,-1,sizeof(head));
n=Read();
for(int i=1;i<n;++i){
int x=Read(),y=Read();
add(x,y),add(y,x);
}
bfs1(1);
for(int i=1;i<=n;++i) if(dis[i]>maxx) maxx=dis[i],s=i;
memset(dis,0,sizeof(dis));
memset(viss,0,sizeof(viss));
bfs1(s);
maxx=0;
for(int i=1;i<=n;++i) if(dis[i]>maxx) maxx=dis[i],t=i;
// cout<<maxx<<'\n';
bfs2(t);
findmax();
// for(int i=1;i<=tot;++i) cout<<que[i]<<' '<<maxlen[i]<<'\n';
find();
}