170815模拟赛

得分

预估: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\n",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\n",f[m]+ans);
26     return 0;
27 }

 

posted @ 2017-08-17 10:16  J_william  阅读(174)  评论(0编辑  收藏  举报