得分
预估:200
实测:100
详情
T1 第K小数 number
思路
我当时想的是两层二分,一层二分ans,然后枚举n,二分m;
理论时间复杂度O(nlogmlog1e18+nlongn+mlogm);
然后二分写挂了。。。
师傅的题解给出的思路是二分ans,正序枚举n,倒序枚举m;
因为n和m已经排好序,所以时间复杂度为O((n+m)log1e18+nlogn+mlogm);
因为数据规模较小,所以在常数上比我稍优;
而且好写,所以我采用后者;
代码实现
1 #include<cstdio> 2 #include<algorithm> 3 #define LL long long 4 using namespace std; 5 const int maxn=2e5+1; 6 LL n,m,k,ans; 7 LL x[maxn],y[maxn]; 8 int main(){ 9 freopen("number.in","r",stdin); 10 freopen("number.out","w",stdout); 11 scanf("%d%d%I64d",&n,&m,&k),k--; 12 for(int i=1;i<=n;i++) scanf("%I64d",&x[i]); 13 for(int i=1;i<=m;i++) scanf("%I64d",&y[i]); 14 sort(x+1,x+n+1); 15 sort(y+1,y+m+1); 16 LL l=1,r=x[n]*y[m],mid,num; 17 int i,j; 18 while(l<=r){ 19 num=0; 20 mid=l+r>>1; 21 i=1,j=m; 22 for(i;i<=n;i++){ 23 while(1ll*x[i]*y[j]>mid) j--; 24 num+=j; 25 } 26 if(num<=k) l=mid+1; 27 if(num>k) r=mid-1; 28 } 29 printf("%I64d ",l); 30 return 0; 31 }
T2 dwarf tower
思路
我的想法可能不太清真,不过理论上和实测都能过;//跑的也不慢;
对于m种合成方式,我建m个虚节点;
建立合成物节点->虚节点->原料节点顺序的单向链接;
跑一边dfs;
对于普通节点,它的花费等于它和它所有儿子值中的最小值;
等于虚节点,他的花费等于它所有儿子的花费和;
代码实现
1 #include<cstdio> 2 #include<iostream> 3 const long long inf=1e9+7; 4 const int maxn=3e5+10; 5 int n,m; 6 int v[maxn]; 7 int h[maxn],hs; 8 int et[maxn],en[maxn]; 9 bool vis[maxn]; 10 void add(int k){ 11 int a,b,c; 12 scanf("%d%d%d",&a,&b,&c); 13 et[++hs]=k,en[hs]=h[a],h[a]=hs; 14 et[++hs]=b,en[hs]=h[k],h[k]=hs; 15 et[++hs]=c,en[hs]=h[k],h[k]=hs; 16 } 17 void dfs(int k){ 18 vis[k]=1; 19 for(int i=h[k];i;i=en[i]){ 20 if(!vis[et[i]]) dfs(et[i]); 21 if(k>n) v[k]=std::min(inf,0ll+v[k]+v[et[i]]); 22 else v[k]=std::min(v[k],v[et[i]]); 23 } 24 } 25 int main(){ 26 freopen("dwarf.in","r",stdin); 27 freopen("dwarf.out","w",stdout); 28 scanf("%d%d",&n,&m); 29 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 30 for(int i=1;i<=m;i++) add(n+i); 31 dfs(1); 32 printf("%d",v[1]); 33 return 0; 34 }
T3 abcd
思路
完全背包;
先对数据进行预处理,解决负数问题;
然后跑背包DP;
f[j]=max_(f[j],f[j-w[i]]+v[i]);
代码实现
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 const int maxn=210; 5 int n,m,num,ans; 6 int a[maxn],b[maxn],c[maxn],d[maxn]; 7 int f[101000],w[3010],v[3010]; 8 int main(){ 9 freopen("abcd.in","r",stdin); 10 freopen("abcd.out","w",stdout); 11 memset(f,-127/3,sizeof(f)),f[0]=0; 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++){ 14 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]); 15 b[i]-=a[i],ans+=a[i]*d[i],m-=a[i]*c[i]; 16 } 17 for(int i=1;i<=n;i++){ 18 for(int j=1;j<=b[i];j<<=1) 19 w[++num]=c[i]*j,v[num]=d[i]*j,b[i]-=j; 20 if(b[i]) w[++num]=b[i]*c[i],v[num]=b[i]*d[i]; 21 } 22 for(int i=1;i<=num;i++) 23 for(int j=m;j>=w[i];j--) 24 f[j]=std::max(f[j-w[i]]+v[i],f[j]); 25 printf("%d ",f[m]+ans); 26 return 0; 27 }