华东师大二月月赛游记

传送门

A.昔我往矣

一看到这题就想到了LCA,然后就开始码,结果码的时候发现用三段跳没法维护翻新的记录与翻新的代价,然后就一格一格的跳,很顺利的TLE
My incorrect code:

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
#define rg register
using namespace std;
const ll INF=10000000000;
ll Read(){
 ll dx=0,fh=1;
 char c=getchar();
 while(c>'9'||c<'0'){
  if(c=='-') fh=-1;
  c=getchar();
 }
 while(c<='9'&&c>='0'){
  dx=dx*10+c-'0';
  c=getchar();
 }
 return dx*fh;
}
ll h[50002],cnt;
struct node{
 ll to,next,val;
}edg[50002];
void Add(ll u,ll v,ll val){
 ++cnt;
 edg[cnt].next=h[u];
 edg[cnt].to=v;
 edg[cnt].val=val;
 h[u]=cnt;
}
ll Newed[50002],n,q,p[6],Place,fa[50002],vis[50002],que[50010],he=0,t=1,dep[50010];
ll chk(ll A,ll B){
 for(ll i=h[A];i;i=edg[i].next) if(edg[i].to==B) return i;
}
ll Work(rg ll A,rg ll B){
 ll sum=0,AA=A,BB=B;
 while(dep[A]!=dep[B]){
  if(dep[A]>dep[B]){
   ll num=chk(A,fa[A]);
   if(!Newed[num]){
    Newed[num]=1;
    sum+=edg[num].val;
   }
   A=fa[A];
  }
  if(dep[B]>dep[A]){
   ll num=chk(B,fa[B]);
   if(!Newed[num]){
    Newed[num]=1;
    sum+=edg[num].val;
   }
   B=fa[B];
  }
 }
 while(A!=B){
  if(fa[A]){
   ll numA=chk(A,fa[A]);
   if(!Newed[numA]){
    Newed[numA]=1;
    sum+=edg[numA].val;
   }
   A=fa[A];
  }
  if(fa[B]){
   ll numB=chk(B,fa[B]);
   if(!Newed[numB]){
    Newed[numB]=1;
    sum+=edg[numB].val;
   }
   B=fa[B]; 
  }
 }
 return sum;
}
void Init(){
 memset(p,0,sizeof(p));
 memset(Newed,0,sizeof(Newed));
}
int main(){
 n=Read();
 for(rg int i=1;i<n;++i){
  ll aa,bb,Val;
  aa=Read();
  bb=Read();
  Val=Read();
  Add(aa+1,bb+1,Val);
  Add(bb+1,aa+1,Val);
 }
 q=Read();
 que[1]=1;
 dep[1]=1;
 while(he<t){
 
  ++he;
  ll u=que[he]; vis[u]=1;
  for(rg int i=h[u];i;i=edg[i].next){
   ll v=edg[i].to;
   if(vis[v]) continue;
   
   dep[v]=dep[u]+1;
   fa[v]=u;
   que[++t]=v;
  }
 }
 for(rg int r=1;r<=q;++r){
  Init();
  p[1]=Read();p[2]=Read();p[3]=Read();p[4]=Read();p[5]=Read();
  ++p[1];++p[2];++p[3];++p[4];++p[5];
  printf("%lld",Work(p[1],p[2])+Work(p[2],p[3])+Work(p[3],p[4])+Work(p[4],p[5]));
 }
 return 0;
}

反思与总结:
暴力出奇迹

B.杨柳依依

比赛的时候想到是BFS,但是时间不够,一看有九分的数据范围k都为一,就想到了骗分方法:起点为那个人的必经之路,就输出起点就行了。期望得分:9分
Wrong Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll INF=10000000000;
ll Read(){
   ll dx=0,fh=1;
   char c=getchar();
   while(c>'9'||c<'0'){
   	if(c=='-')	fh=-1;
   	c=getchar();
   }
   while(c<='9'&&c>='0'){
   	dx=dx*10+c-'0';
   	c=getchar();
   }
   return dx*fh;
}
ll h[50002],cnt;
struct node{
   ll to,next;
}edg[50002];
void Add(ll u,ll v){
   ++cnt;
   edg[cnt].next=h[u];
   edg[cnt].to=v;
   h[u]=cnt;
}
ll m,n,k,s[100000],e[100000];
int main(){
   n=Read(),m=Read();
   for(int i=1;i<=m;++i){
   	int aa=Read(),bb=Read();
   	Add(aa,bb);Add(bb,aa);
   }
   k=Read();
   for(int i=1;i<=k;++i)
   	s[i]=Read(),e[i]=Read();
   if(k==1)	printf("%d",s[1]);
   else printf("不会qwq");
   return 0;
}

比赛完之后看题解,就这个题的题解能看懂,把这个题订了一下
算法分析:
以每个人为起点BFS一遍,记录每个点的步数,当到达这个点的时候步数为最短步数时,记录前驱的数量与个数,然后再两遍递归遍历来找这个人到每个点的次数和总路径,二者相除,算出这个点一个人时的概率,不断地加上下一个人的概率,最后统计概率最大的节点的编号
但是鄙人的递归遍历遇到环时退不出去了
My incorrect Code:

#include<bits/stdc++.h>
using namespace std;
int Read(){
int dx=0,fh=1;
char c=getchar();
while(c>'9'||c<'0'){
 if(c=='-') fh=-1;
 c=getchar();
}
while(c<='9'&&c>='0'){
 dx=dx*10+c-'0';
 c=getchar();
}
return dx*fh;
}
int h[50002],cnt;
struct node{
int to,next;
}edg[50002];
void Add(int u,int v){
++cnt;
edg[cnt].next=h[u];
edg[cnt].to=v;
h[u]=cnt;
}
double ans,Chance[5001];
int step[5001],flag[5001],num,az[5001],VVis[5001],Vis[5001],m,n,r,k,s[2001],e[2001],que[100000],he,ta,pre[5001][100],cpre[5001],ways[2001],vis[5001];
void Record(int u){
++az[u];
// printf("record(%d),cpre[%d]=%d\n",u,u,cpre[u]);
int sum=0;
for(int i=1;i<=cpre[u];++i){
 int v=pre[u][i];
 Record(v);
}
}
void Chk(int u){
Vis[u]=1;
Chance[u]+=double(double(az[u])/double(ways[e[r]]));
// printf("Chance(%d)=%lf,az[%d]=%d,ways[%d]=%d\n",u,Chance[u],u,az[u],e[r],ways[e[r]]);
for(int i=h[u];i;i=edg[i].next){
 int v=edg[i].to;
 if(!vis[v]||Vis[v]) continue;
 Chk(v);
}
}
int main(){
n=Read(),m=Read();
for(int i=1;i<=m;++i){
 int aa=Read(),bb=Read();
 Add(aa,bb);Add(bb,aa);
}
k=Read();
for(int i=1;i<=k;++i)
 s[i]=Read(),e[i]=Read();
for(r=1;r<=k;++r){
 memset(az,0,sizeof(az));
 memset(que,0,sizeof(que));
 memset(Vis,0,sizeof(Vis));
 memset(vis,0,sizeof(vis));
 memset(pre,0,sizeof(pre));
 memset(cpre,0,sizeof(cpre));
 memset(ways,0,sizeof(ways));
 memset(flag,0,sizeof(flag));
 memset(step,0,sizeof(step));
 he=0,ta=1;
 que[ta]=s[r];
 while(he<ta){
  ++he;
  int u=que[he];
//   printf("u=%d,head=%d,tail=%d\n",u,he,ta);
  vis[u]=1;
  for(int i=h[u];i;i=edg[i].next){
   int v=edg[i].to;
//    printf("to:%d\n",v);
   if(!vis[v]){
    if(flag[v]&&flag[v]<step[u]+1) continue;
    step[v]=step[u]+1;
    pre[v][++cpre[v]]=u;
    flag[v]=step[v];
    que[++ta]=v;
    if(u==s[r]) ++ways[v];
    ways[v]+=ways[u];
   }
  }
 }
 if(flag[e[r]]){
  vis[e[r]]=1;
  Record(e[r]);
 }
 Chk(s[r]);
} 
for(int i=0;i<n;++i){
 if(ans<Chance[i]){
  ans=Chance[i];
  num=i;
 }
}
printf("%d",num);
return 0;
}

总结与反思:

  • 骗分出省一qwq
  • 递归要注意好终止条件

C.今我来思

玄学题目,样例过了,其他全错
错误示范:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll INF=10000000000;
ll Read(){
 ll dx=0,fh=1;
 char c=getchar();
 while(c>'9'||c<'0'){
  if(c=='-') fh=-1;
  c=getchar();
 }
 while(c<='9'&&c>='0'){
  dx=dx*10+c-'0';
  c=getchar();
 }
 return dx*fh;
}
ll n,q,Cheat,l[100004],r[100004],a[100004],used[100004],A[100004],f[100004],flag[100004];
int main(){
 n=Read(),q=Read();
 for(ll i=0;i<=n;++i) a[i]=-1;
 for(ll i=0;i<n;++i) l[i]=-1,r[i]=-1;
 for(ll R=1;R<=q;++R){
  ll le,num,ri;
  le=Read(),ri=Read(),num=Read();
  ++le;++ri;
  if(l[num]==-1&&r[num]==-1){
   l[num]=le;r[num]=ri; }
  else{
   if((l[num]>ri||le>r[num]))   Cheat=1;
   else{
    r[num]=max(r[num],ri);
    l[num]=min(l[num],le);
   }
  } 
  for(ll i=0;i<n-1;++i)
   for(ll j=i+1;j<=n-1;++j)
    if(r[i]<=r[j]&&l[i]>=l[j]&&l[i]!=-1&&l[j]!=-1){
     Cheat=1;
    }
  for(ll i=le;i<=ri;++i) a[i]=max(a[i],num);
 }
 for(ll i=0;i<n;++i){
  for(ll j=1;j<=n;++j){
   if(a[j]<=i&&!flag[j]){
    A[j]=i;
    used[i]=1;
    flag[j]=1;
    break;
   } 
  }
  if(used[i]==0){
   Cheat=1;
   break;
  }
 }
 if(Cheat) for(ll i=1;i<=n;++i) printf("-1 ");
 else for(ll i=1;i<=n;++i) printf("%d ",A[i]);
 return 0;
}

D.雨雪霏霏

暴力出奇迹!(bingmeiyou)

#include<bits/stdc++.h>
using namespace std;
int Read(){
 int dx=0,fh=1;
 char c=getchar();
 while(c>'9'||c<'0'){
  if(c=='-') fh=-1;
  c=getchar();
 }
 while(c<='9'&&c>='0'){
  dx=dx*10+c-'0';
  c=getchar();
 }
 return dx*fh;
}
int cmax,h,t,que[5000010][3],R,C,Q,Co[50001][101],L[50001][101],Hush[50001],dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};
bool vis[50001][101];
int main(){
// freopen("az.txt","r",stdin);
 R=Read();C=Read();Q=Read();
 for(int i=1;i<=R;++i)
  for(int j=1;j<=C;++j)
   L[j][i]=Read();
 for(int i=1;i<=R;++i)
  for(int j=1;j<=C;++j)
   Co[j][i]=Read(),cmax=max(cmax,Co[j][i]);
 for(int r=1;r<=Q;++r){
  int state=Read();
  if(state==1){
   int aa,bb,cc;
   aa=Read();bb=Read();cc=Read();
   Co[aa][bb]=cc;cmax=max(cc,cmax);
  }
  else if(state==2){
   memset(Hush,0,sizeof(Hush));
   memset(vis,0,sizeof(vis));
   memset(que,0,sizeof(que));
   int x=Read(),y=Read(),H=Read();
   if(H<L[x][y]){
    printf("0\n");
    continue;
   }
   else{
    t=1;h=0;
    que[1][1]=x;
    que[1][2]=y;
    vis[x][y]=1;
    while(h<t){
     ++h;
     int X=que[h][1],Y=que[h][2];
     Hush[Co[X][Y]]=1;
     if(X>C||X<1||Y>R||Y<1) continue;
//     printf("h=%d\tt=%d\t,X=%d\t,Y=%d\n",h,t,X,Y);
     for(int i=1;i<=4;++i){
      int x1=X+dx[i],y1=Y+dy[i];
      if(H<L[x1][y1]||vis[x1][y1]||x1>C||x1<1||y1>R||y1<1) continue;
      vis[x1][y1]=1;
      ++t;
      
//      printf("Color(%d,%d)=%d\n",x1,y1,Co[x1][y1]);
      que[++t][1]=x1;
      que[t][2]=y1;
     }
    }
   }
   int ans=0;
   for(int i=1;i<=cmax;++i) ans+=Hush[i];
   printf("%d\n",ans);
  }
 }
 return 0;
}

在这里插入图片描述
总结与反思:
暴力出奇迹
然而捆绑测试中并不能这样

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值