距離盃賽已經好久了,然而我如今纔打總結。。node
我好慘的說..兩場才380。。。ios
DAY 1數組
第一題 toyide
送分題,模擬的時候+一下再mod一下就好。spa
[當時打完這題就沒再看一眼了,好方的說]ssr
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define Maxn 100010 int a[Maxn]; char s[Maxn][20]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&a[i]); scanf("%s",s[i]); } int now=0; for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); y%=n; if(a[now]==1&&x==0) now=(now+y)%n; else if(a[now]==1) now=(now+n-y)%n; else if(x==0) now=(now+n-y)%n; else now=(now+y)%n; } printf("%s\n",s[now]); return 0; }
第二題 runningcode
感受這題是全場最難的【是吧??orm
但其實【啊好像也不是很難。。blog
怎麼比賽的時候就腦子那麼亂呢排序
個人方法是,把路徑分紅兩段,而後lca的特殊算。
假如lca在st上面,假設這條路徑對z有貢獻(z在lca和st之間),那麼dep[z]-dep[st]=w[z] => dep[z]-w[z]=dep[st]
那麼對於z來講,就是求通過本身的路徑中dep等於dep[z]-w[z]的有多少個。
對於路徑,咱們在st上打一個加入標記,在lca上打一個刪除標記,那麼對於z,就是求其子樹和(每一個點用dfs序作,問題變成求區間和,單點修改,區間詢問,能夠用樹狀數組維護)。
對於加入和刪除,咱們按照st的dep排序,對於每一個點,咱們按照dep[z]-dep[st]排序,值相等是一塊兒作,這時O(n+m)的。
對於右半邊的路徑相似,有2*dep[lca]-dep[st]=dep[z]+w[z]。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define Maxn 300010 #define Maxm 300010 struct node { int x,y,next,c; }t[Maxn*2];int len=0; int n,m; struct hp { int x,y,c; }q[Maxm],qq[Maxm],nq[Maxn]; int l1,l2; int first[Maxn]; void ins(int x,int y) { t[++len].x=x;t[len].y=y; t[len].next=first[x];first[x]=len; } bool cmp(hp x,hp y) {return x.c<y.c;} int son[Maxn],dep[Maxn],sm[Maxn]; int fa[Maxn]; void dfs(int x,int f) { sm[x]=1;dep[x]=dep[f]+1; fa[x]=f; son[x]=0; for(int i=first[x];i;i=t[i].next) if(t[i].y!=f) { int y=t[i].y; dfs(y,x); sm[x]+=sm[y]; if(sm[y]>sm[son[x]]) son[x]=y; } } int tp[Maxn],dfn[Maxn],rt[Maxn],cnt=0; void dfs2(int x,int tpp) { tp[x]=tpp;rt[x]=dfn[x]=++cnt; if(son[x]) dfs2(son[x],tpp),rt[x]=rt[son[x]]; for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x]) { int y=t[i].y; dfs2(y,y); rt[x]=rt[y]; } } int lca(int x,int y) { int tt; while(tp[x]!=tp[y]) { if(dep[tp[x]]<dep[tp[y]]) tt=x,x=y,y=tt; x=fa[tp[x]]; } if(dep[x]<dep[y]) return x; return y; } int w[Maxn],ans[Maxn],c[Maxn]; void add(int x,int y) { for(int i=x;i<=n;i+=i&(-i)) c[i]+=y; } int query(int l,int r) { int ans=0; for(int i=r;i>=1;i-=i&(-i)) ans+=c[i]; l--; for(int i=l;i>=1;i-=i&(-i)) ans-=c[i]; return ans; } void ffind() { int l,r; l=2,r=1; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { int x=nq[i].x; if(i==1||nq[i].c!=nq[i-1].c) { for(int j=l;j<r;j++) { add(q[j].x,-1),add(q[j].y,1); } l=r; while(q[l].c<nq[i].c&&l<=l1) l++; r=l; } while(q[r].c==nq[i].c&&r<=l1) { add(q[r].x,1);add(q[r].y,-1); //printf("add %d\n",r); r++; } ans[x]+=query(dfn[x],rt[x]); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y);ins(y,x); } for(int i=1;i<=n;i++) scanf("%d",&w[i]); dfs(1,0); dfs2(1,1); l1=l2=0; memset(ans,0,sizeof(ans)); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d",&x,&y); z=lca(x,y); q[++l1].x=dfn[x];q[l1].y=dfn[z];q[l1].c=dep[x]; qq[++l2].x=dfn[y];qq[l2].y=dfn[z];qq[l2].c=2*dep[z]-dep[x]; if(w[z]==dep[x]-dep[z]) ans[z]++; } sort(q+1,q+1+l1,cmp); for(int i=1;i<=n;i++) nq[i].x=i,nq[i].c=dep[i]+w[i]; sort(nq+1,nq+1+n,cmp); ffind(); for(int i=1;i<=l2;i++) q[i]=qq[i]; l1=l2; sort(q+1,q+1+l1,cmp); for(int i=1;i<=n;i++) nq[i].x=i,nq[i].c=dep[i]-w[i]; sort(nq+1,nq+1+n,cmp); ffind(); for(int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n"); return 0; }
第三題 classroom
實際上是一個很明顯的指望DP。【當時腦抽again = = toxic
狀態f[i][j][0]表示前i段,用j次機會,最後一次不使用機會的指望值。
狀態f[i][j][1]表示前i段,用j次機會,最後一次使用機會的指望值。
f[i][j][0]=min(f[i-1][j][0]+1.0*dis[c[i-1]][c[i]])
f[i][j][0]=min(f[i-1][j][1]+1.0*dis[d[i-1]][c[i]]*k[i-1]+(1-k[i-1])*dis[c[i-1]][c[i]]);
f[i][j][1]=min(f[i-1][j-1][0]+k[i]*(dis[c[i-1]][d[i]])+(1-k[i])*(dis[c[i-1]][c[i]]));
f[i][j][1]=min(f[i-1][j-1][1]+ k[i]*(dis[d[i-1]][d[i]]*k[i-1]+dis[c[i-1]][d[i]]*(1-k[i-1]))+ (1-k[i])*(dis[d[i-1]][c[i]]*k[i-1]+dis[c[i-1]][c[i]]*(1-k[i-1])));
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 #define Maxn 2010 9 #define INF 0xfffffff 10 11 int c[Maxn],d[Maxn]; 12 double f[Maxn][Maxn][2],k[Maxn]; 13 14 int n,m,v,e; 15 16 int mmin(int x,int y) {return x<y?x:y;} 17 double mymin(double x,double y) {return x<y?x:y;} 18 19 int dis[Maxn][Maxn]; 20 21 void floyd() 22 { 23 for(int l=1;l<=v;l++) 24 for(int i=1;i<=v;i++) 25 for(int j=1;j<=v;j++) 26 dis[i][j]=mmin(dis[i][j],dis[i][l]+dis[l][j]); 27 } 28 29 int main() 30 { 31 scanf("%d%d%d%d",&n,&m,&v,&e); 32 for(int i=1;i<=n;i++) scanf("%d",&c[i]); 33 for(int i=1;i<=n;i++) scanf("%d",&d[i]); 34 for(int i=1;i<=n;i++) scanf("%lf",&k[i]); 35 memset(dis,63,sizeof(dis)); 36 for(int i=1;i<=e;i++) 37 { 38 int x,y,c; 39 scanf("%d%d%d",&x,&y,&c); 40 dis[x][y]=mmin(dis[x][y],c); 41 dis[y][x]=mmin(dis[y][x],c); 42 } 43 for(int i=1;i<=v;i++) dis[i][i]=0; 44 floyd(); 45 46 for(int i=1;i<=n;i++) 47 for(int j=0;j<=n;j++) 48 f[i][j][0]=f[i][j][1]=INF; 49 double ans=INF; 50 f[1][0][0]=f[1][1][1]=0;f[1][1][0]=0; 51 for(int i=2;i<=n;i++) 52 for(int j=0;j<=i&&j<=m;j++) 53 { 54 //printf("%.2lf\n",ans); 55 //bu yong 56 f[i][j][0]=mymin(f[i][j][0],f[i-1][j][0]+1.0*dis[c[i-1]][c[i]]); 57 f[i][j][0]=mymin(f[i][j][0],f[i-1][j][1]+1.0*dis[d[i-1]][c[i]]*k[i-1]+(1-k[i-1])*dis[c[i-1]][c[i]]); 58 59 //yong 60 if(j>0) 61 { 62 f[i][j][1]=mymin(f[i][j][1],f[i-1][j-1][0]+k[i]*(dis[c[i-1]][d[i]])+(1-k[i])*(dis[c[i-1]][c[i]])); 63 f[i][j][1]=mymin(f[i][j][1],f[i-1][j-1][1]+ 64 k[i]*(dis[d[i-1]][d[i]]*k[i-1]+dis[c[i-1]][d[i]]*(1-k[i-1]))+ 65 (1-k[i])*(dis[d[i-1]][c[i]]*k[i-1]+dis[c[i-1]][c[i]]*(1-k[i-1]))); 66 } 67 } 68 for(int i=0;i<=m&&i<=n;i++) ans=mymin(ans,f[n][i][0]), 69 ans=mymin(ans,f[n][i][1]); 70 printf("%.2lf\n",ans); 71 return 0; 72 }
第一天 100+25+55 哭泣
第二題交了純暴力,第三題錯誤DP。。
DAY 2
第一題 problem
用楊輝三角搞一搞就行了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 #define Maxn 2010 8 9 int p[Maxn],f[Maxn][Maxn]; 10 int k; 11 12 13 int c[Maxn][Maxn],ans[Maxn][Maxn]; 14 15 void init() 16 { 17 for(int i=0;i<=2000;i++) c[i][0]=1; 18 for(int i=1;i<=2000;i++) 19 for(int j=1;j<=i;j++) 20 c[i][j]=(c[i-1][j-1]+c[i-1][j])%k; 21 22 memset(f,0,sizeof(f)); 23 for(int i=1;i<=2000;i++) 24 { 25 f[i][0]=0; 26 for(int j=1;j<=i;j++) 27 { 28 f[i][j]=f[i][j-1]; 29 if(c[i][j]==0) f[i][j]++; 30 } 31 for(int j=i+1;j<=2000;j++) f[i][j]=f[i][j-1]; 32 } 33 for(int i=1;i<=2000;i++) ans[1][i]=f[1][i]; 34 for(int i=2;i<=2000;i++) 35 for(int j=1;j<=2000;j++) ans[i][j]=ans[i-1][j]+f[i][j]; 36 } 37 38 int main() 39 { 40 int T; 41 scanf("%d%d",&T,&k); 42 init(); 43 while(T--) 44 { 45 int n,m; 46 scanf("%d%d",&n,&m); 47 printf("%d\n",ans[n][m]); 48 } 49 return 0; 50 }
第二題 earthworm
在暴力的基礎上看出來有單調性就能夠AC了。
切出來的左邊遞減,右邊也遞減,每次取三部分的最大值出來切,注意不要想成所有+q,用一個累加器,而後切出來的那部分-q是同樣的。
//代碼很醜,由於在洛谷上調TLE,,洛谷好慢的說。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 #define Maxn 100010 8 #define Maxm 7000010 9 #define INF 0xfffffff 10 #define LL long long 11 12 int a[Maxn]; 13 14 LL add=0; 15 LL v1[Maxm],v2[Maxm]; 16 17 int n,m,q,u,v,t; 18 int l1,l2; 19 20 bool cmp(int x,int y) {return x>y;} 21 22 23 int main() 24 { 25 scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t); 26 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 27 sort(a+1,a+1+n,cmp); 28 l1=1,l2=1; 29 v1[0]=v2[0]=0; 30 a[0]=1; 31 for(LL i=1;i<=m;i++) 32 { 33 34 35 LL now=-INF; 36 now*=10000000; 37 if(a[0]<=n) now=now>a[a[0]]?now:a[a[0]]; 38 if(l1<=v1[0]) now=now>v1[l1]?now:v1[l1]; 39 if(l2<=v2[0]) now=now>v2[l2]?now:v2[l2]; 40 if(a[0]<=n&&now==a[a[0]]) a[0]++; 41 else if(l1<=v1[0]&&now==v1[l1]) l1++; 42 else if(l2<=v2[0]&&now==v2[l2]) l2++; 43 now+=add; 44 45 46 47 48 49 50 if(i%t==0) printf("%lld ",now); 51 add+=q; 52 LL x=now*u/v,y=now-x; 53 v1[++v1[0]]=x-add;v2[++v2[0]]=y-add; 54 } 55 printf("\n"); 56 for(int i=1;i<=n+m;i++) 57 { 58 59 60 61 LL now=-INF; 62 now*=10000000; 63 if(a[0]<=n) now=now>a[a[0]]?now:a[a[0]]; 64 if(l1<=v1[0]) now=now>v1[l1]?now:v1[l1]; 65 if(l2<=v2[0]) now=now>v2[l2]?now:v2[l2]; 66 if(a[0]<=n&&now==a[a[0]]) a[0]++; 67 else if(l1<=v1[0]&&now==v1[l1]) l1++; 68 else if(l2<=v2[0]&&now==v2[l2]) l2++; 69 now+=add; 70 71 if(i%t==0) printf("%lld ",now); 72 } 73 printf("\n"); 74 return 0; 75 }
第三題 angrybirds
其實就是狀壓dp啊
注意精度,不要*100而後強轉int【我就死在強轉int,否則用round也能夠
還有一個小地方就是,你可能會枚舉兩個點,是18^2的,可是其實你能夠只枚舉一個點,規定這一次必定先把某頭豬弄下來(由於你後面總有一次要把這頭豬弄下來的,不如如今先作了,反正沒什麼區別),這樣就是一個18,這樣就能夠過了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 #define Maxd 300010 8 #define INF 0xfffffff 9 10 double xx[20],yy[20]; 11 12 int f[Maxd]; 13 int n,m; 14 15 int gcd(int a,int b) 16 { 17 if(b==0) return a; 18 return gcd(b,a%b); 19 } 20 21 double fabs(double x) {return x<0?-x:x;} 22 23 int sum; 24 int get_s(int a,int b,int s) 25 { 26 int ss=s; 27 double A,B; 28 A=(xx[b]*yy[a]-xx[a]*yy[b])*1.0/(xx[b]*xx[a]*xx[a]-xx[a]*xx[b]*xx[b]); 29 B=(yy[a]-A*xx[a]*xx[a])*1.0/xx[a]; 30 if(A>=0) 31 { 32 return -1; 33 } 34 sum=0; 35 for(int i=1;i<=n;i++) if((1<<i-1)&s) 36 { 37 if(fabs(A*xx[i]*xx[i]+B*xx[i]-yy[i])<0.000001) ss^=(1<<i-1),sum++; 38 } 39 return ss; 40 } 41 42 int mymin(int x,int y) {return x<y?x:y;} 43 44 int ffind(int s) 45 { 46 if(f[s]!=-1) return f[s]; 47 f[s]=INF; 48 for(int i=1;i<=n;i++) if((1<<i-1)&s) 49 { 50 for(int j=i+1;j<=n;j++) if((1<<j-1)&s) 51 { 52 int ss=get_s(i,j,s); 53 if(ss!=-1) f[s]=mymin(f[s],ffind(ss)+1); 54 } 55 break; 56 } 57 for(int i=1;i<=n;i++) if((1<<i-1)&s) 58 { 59 f[s]=mymin(f[s],ffind(s-(1<<i-1))+1); 60 break; 61 } 62 return f[s]; 63 } 64 65 int main() 66 { 67 int T; 68 scanf("%d",&T); 69 while(T--) 70 { 71 scanf("%d%d",&n,&m); 72 for(int i=1;i<=n;i++) 73 { 74 double nx,ny; 75 scanf("%lf%lf",&nx,&ny); 76 xx[i]=nx;yy[i]=ny; 77 } 78 memset(f,-1,sizeof(f)); 79 f[0]=0; 80 int ans=ffind((1<<n)-1); 81 printf("%d\n",ans); 82 } 83 return 0; 84 }
次日 100+55+70 哭泣
被虐的好慘,主要是仍是太傻了,其實題目說難也不是很難的。。。。
上面是bac回的AC代碼。。。。
2016-12-07 14:02:45