problem1 link
先计算出最上面、最下面一层,根据最上面一层的数量计算答案。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class PyramidOfCubes { public double surface(int K) { int s=0,m=-1; for(int i=1;;++i) { if(s+i*i>=K) { m=i; break; } s+=i*i; } for(int i=m;;--i) { if(i*i>=K) { s=i; break; } K-=i*i; } double result=0.0; result+=m*m*2; result+=(s+m)*(m-s+1)/2*4; int row=(K+s-1)/s; int col=K>=s?s:K; result-=s*4-(row+col)*2; if(s==m) { result-=m*m*2-K*2; } return result; } }
problem2 link
拿一个线段树维护中位数即可。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class FloatingMedian { static final int N=65537; static class node { int L,R,num; } node[] A=new node[N<<2]; int[] a=null; void build(int t,int L,int R) { A[t]=new node(); A[t].L=L; A[t].R=R; A[t].num=0; if(L==R) return; int M=(L+R)>>1; build(t<<1,L,M); build(t<<1|1,M+1,R); } void insert(int t,int p,int d) { A[t].num+=d; if(A[t].L==A[t].R) { return; } int M=(A[t].L+A[t].R)>>1; if(p<=M) { insert(t<<1,p,d); } else { insert(t<<1|1,p,d); } } int get(int t,int k) { if(A[t].L==A[t].R){ return A[t].L; } if(A[t<<1].num>=k) { return get(t<<1,k); } return get(t<<1|1,k-A[t<<1].num); } public long sumOfMedians(int seed, int mul, int add, int n, int K) { a=new int[n+1]; a[1]=seed; for(int i=2;i<=n;++i) { a[i]=(int)(((long)a[i-1]*mul+add)&65535); } build(1,0,N-1); long result=0; final int T=(K+1)>>1; for(int i=1;i<=n;++i) { insert(1,a[i],1); if(i>=K) { result+=get(1,T); insert(1,a[i-K+1],-1); } } return result; } }
problem3 link
f[S][k][t]表示已经选择的块的集合为$S$,最上面一个是第$k$块,$t$表示朝下的面的类型,有三种。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class BoxTower { int[][][] f=null; int getheight(int[] x,int[] y,int[] z,int k,int t) { if(t==0) { return z[k]; } else if(t==1) { return y[k]; } else { return x[k]; } } boolean check(int[] x,int[] y,int[] z,int k1,int t1,int k2,int t2) { int r1=t1==2?y[k1]:x[k1]; int c1=t1==0?y[k1]:z[k1]; int r2=t2==2?y[k2]:x[k2]; int c2=t2==0?y[k2]:z[k2]; return r1>=r2&&c1>=c2||r1>=c2&&c1>=r2; } public int tallestTower(int[] x, int[] y, int[] z) { final int n=x.length; f=new int[1<<n][n][3]; for(int i=0;i<(1<<n);++i) { for(int j=0;j<n;++j) { if((i&(1<<j))!=0) { continue; } if(i==0) { f[1<<j][j][0]=getheight(x,y,z,j,0); f[1<<j][j][1]=getheight(x,y,z,j,1); f[1<<j][j][2]=getheight(x,y,z,j,2); continue; } for(int k=0;k<n;++k) { if((i&(1<<k))==0) { continue; } for(int t1=0;t1<3;++t1) { for(int t2=0;t2<3;++t2) { if(check(x,y,z,k,t1,j,t2)) { int t=f[i][k][t1]+getheight(x,y,z,j,t2); f[i|1<<j][j][t2]=Math.max(f[i|1<<j][j][t2],t); } } } } } } int result=0; for(int i=0;i<(1<<n);++i) { for(int j=0;j<n;++j) { for(int k=0;k<3;++k) { result=Math.max(result,f[i][j][k]); } } } return result; } }