Day1 T1
签到题,模拟一下随便写就能过。
不过小心像我一样表打错傻逼的调了10min。
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstdio> using namespace std; int La=0,Lb=0,N=0; int xl_a[205]={0},xl_b[205]={0}; int check[5][5]={{0,-1,1,1,-1},{1,0,-1,1,-1},{-1,1,0,-1,1},{-1,-1,1,0,1},{1,1,-1,-1,0}}; int main(void) { freopen("rps.in","r",stdin); freopen("rps.out","w",stdout); scanf("%d%d%d",&N,&La,&Lb); for(int i=1;i<=La;i++)scanf("%d",&xl_a[i]); for(int i=1;i<=Lb;i++)scanf("%d",&xl_b[i]); int a=0,b=0,ans_a=0,ans_b=0; for(int i=1;i<=N;i++) { a=xl_a[i%La]; if(!(i%La))a=xl_a[La]; b=xl_b[i%Lb]; if(!(i%Lb))b=xl_b[Lb]; if(check[a][b]==1){ans_a++;continue;} if(check[a][b]!=0){ans_b++;;continue;} } printf("%d %d",ans_a,ans_b); return 0; }
T2
没什么难度……不知道为什么能卡当时的我只拿70分。
大概是不知道n个点n-1条边就是树?
最开始写代码的时候没考虑兄弟节点的情况……后面紧急补上去了,还好发现了不然岂不是又得炸。
一涉及到取模我的代码风格就变得乱七八糟。
简述一下,我们对这棵树从1开始dfs,每到一个节点,就先更新答案(和它父亲的父亲)。
然后枚举它的儿子节点,记录两个参数,max_son和tot,max_son是它儿子节点中权值最大的那个,tot是它所有儿子的权值和。
max_son是更新第一个最大值的答案的,tot是更新第二个答案的。
顺便提醒一下,因为题面上说的是有序点对,所以说我们每次更新第二个答案的时候都要记住乘个2……【血泪教训】
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstdio> using namespace std; struct lb { int nw; int nxt; }; lb line[400003]; int n=0,cnt=0,val[200003]={0},head[200003]={0}; int fa[200003]={0},ans1=0,ans2=0; void add(int f,int t); void dfs(int nw); int main(void) { freopen("link.in","r",stdin); freopen("link.out","w",stdout); scanf("%d",&n); int a=0,b=0; for(int i=1;i<=n-1;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(int i=1;i<=n;i++)scanf("%d",&val[i]); fa[1]=0; dfs(1); printf("%d %d",ans1,ans2); return 0; } void add(int f,int t) { line[++cnt].nw=t; line[cnt].nxt=head[f]; head[f]=cnt; return; } void dfs(int nw) { if(nw>n)return; if(fa[fa[nw]]) { ans1=max(ans1,val[nw]*val[fa[fa[nw]]]); ans2+=val[nw]*val[fa[fa[nw]]]*2; ans2%=10007; } int next=0,max_son=0,tot=0; for(int i=head[nw];i>0;i=line[i].nxt) { next=line[i].nw; if(next==fa[nw])continue; ans1=max(ans1,val[next]*max_son); ans2+=(tot%10007)*val[next]*2; ans2%=10007; max_son=max(max_son,val[next]); tot+=val[next]; tot%=10007; fa[next]=nw; dfs(next); } return; }
T3
我和昨年一样没有长进【不还是多得了五分的】
剩下的都是TLE。
代码风格无论怎么说还是变了一些的。
这题就是个背包,完全=A=,但是我写得丑写不过……
昨年代码↓
#include <iostream> #include <fstream> #include <cstdlib> #include <cstring> #include <cmath> using namespace std; ifstream fin("bird.in"); ofstream fout("bird.out"); bool jz[10002][1002]={0};//0表示可通行,1表示有管道 int ss[2][10002]={0};//0表示点击后上升,1表示向下坠落 int DP[10002][1002]={0};//DP[i][j]表示在x坐标为i,y坐标为j下最小点击数 bool gd[10002]={0};//记录每一x坐标是否有管道 int Lx=0,Ly=0,Gds=0; int main(void) { fin>>Lx>>Ly>>Gds; for(int i=0;i<Lx;i++)fin>>ss[0][i]>>ss[1][i]; int Gx=0,Up=0,Down=0; for(int i=1;i<=Gds;i++) { fin>>Gx>>Down>>Up; for(int j=0;j<=Down;j++)jz[Gx][j]=true; for(int j=Ly;j>=Up;j--)jz[Gx][j]=true; gd[Gx]=true; } memset(DP,127/2,sizeof(DP)); for(int i=1;i<=Ly;i++)DP[0][i]=0; int ans=0x7fffffff,tgs=0,nxt=0; bool pd=false; for(int i=0;i<=Lx;i++) { ans=0x7fffffff; pd=false; for(int j=1;j<=Ly;j++) { if(DP[i][j]==1061109567)continue; if(jz[i][j])continue; pd=true; if(!jz[i+1][j-ss[1][i]]&&j-ss[1][i]>0)//如果不点击下一回合也不会死亡 { DP[i+1][j-ss[1][i]]=min(DP[i+1][j-ss[1][i]],DP[i][j]); if(DP[i+1][j-ss[1][i]]<ans)ans=DP[i+1][j-ss[1][i]]; } for(int k=1;k<=Ly;k++) { nxt=k*ss[0][i];//点击k次后下一次上升的位置 if(nxt+j>Ly)nxt=Ly-j; if(jz[i+1][j+nxt])continue; DP[i+1][j+nxt]=min(DP[i+1][j+nxt],DP[i][j]+k); if(DP[i+1][j+nxt]<ans)ans=DP[i+1][j+nxt]; if(nxt==Ly-j)break; } } if(!pd)break; if(gd[i])tgs++; } if(tgs==Gds)fout<<"1\n"<<ans; else fout<<"0\n"<<tgs; return 0; }
今年的↓
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int n=0,m=0,k=0,bef[10005]={0}; int up[10005]={0},down[10005]={0},dp[2][1005]={0}; bool check[10005][1003]={0}; const int INF=2139062143; int main(void) { freopen("bird.in","r",stdin); freopen("bird.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++)scanf("%d%d",&up[i],&down[i]); int a=0,b=0,c=0; for(int i=1;i<=k;i++) { scanf("%d%d%d",&a,&b,&c); for(int j=0;j<=b;j++)check[a+1][j]=1; for(int j=c;j<=m;j++)check[a+1][j]=1; bef[a+1]++; } for(int i=1;i<=n;i++)bef[i]+=bef[i-1]; memset(dp,0x7f,sizeof(dp)); for(int i=1;i<=m;i++)dp[1][i]=0; int u=0,d=0,mark=0,ans=INF,loop=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(dp[i&1][j]!=INF&&!check[i][j]) { mark=i; loop=max((m-j)/up[i]+1,1); for(int k=1;k<=loop;k++) { u=min(m,j+up[i]*k); if(!check[i+1][u])dp[(i+1)&1][u]=min(dp[(i+1)&1][u],dp[i&1][j]+k); if(i==n)ans=min(ans,dp[(i+1)&1][u]); } d=max(0,j-down[i]); if(d==0)continue; if(!check[i+1][d])dp[(i+1)&1][d]=min(dp[(i+1)&1][d],dp[i&1][j]); if(i==n)ans=min(ans,dp[(i+1)&1][d]); } } for(int j=1;j<=m;j++)dp[i&1][j]=INF; } if(mark<n) { printf("0\n%d",bef[mark]); return 0; } printf("1\n%d",ans); return 0; }