Round A 2020 - Kick Start 2020
Allocation
题意:n(1e5)个数,选出尽可能多的数使他们总和小于等于b。
思路:排序,尽可能取小。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0;int f=1;char ch=getchar(); 6 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 8 } 9 void lrd(LL &x){ 10 x=0;int f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 13 } 14 const int INF=1e9; 15 const LL LINF=1e18; 16 const int N=1e5+10; 17 using namespace std; 18 int T,n,a[N],b; 19 int main(){ 20 // freopen("in.txt","r",stdin); 21 rd(T); 22 for(int t=1;t<=T;t++){ 23 rd(n);rd(b); 24 for(int i=1;i<=n;i++)rd(a[i]); 25 sort(a+1,a+n+1);int mx=0; 26 for(int i=1;i<=n;i++){ 27 b-=a[i]; 28 if(b >= 0)mx=i; 29 else break; 30 } 31 printf("Case #%d: %d\n",t,mx); 32 } 33 return 0; 34 } 35 /**/
Plates
题意:n(50)组数字,每组k(30)个,选出p个数,使得和最大,如果要选择一个数字就必须选择其所在组中它前面的所有数字。
思路:fij表示前i组,一共选了j个数最大值是多少,每个fij枚举当前组取前多少个数字更新答案。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0;int f=1;char ch=getchar(); 6 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 8 } 9 void lrd(LL &x){ 10 x=0;int f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 13 } 14 const int INF=1e9; 15 const LL LINF=1e18; 16 const int N=55; 17 const int K=35; 18 using namespace std; 19 int T,n,k,p; 20 int f[N][N*K]; 21 int a[N][K]; 22 int main(){ 23 // freopen("in.txt","r",stdin); 24 rd(T); 25 for(int t=1;t<=T;t++){ 26 rd(n);rd(k);rd(p); 27 for(int i=1;i<=n;i++) 28 for(int j=1;j<=k;j++) 29 rd(a[i][j]); 30 memset(f,0,sizeof(f)); 31 for(int i=0;i<n;i++){ 32 int now=0; 33 for(int j=0;j<=k;j++){ 34 now+=a[i+1][j]; 35 int tmp=min(i*k,p); 36 for(int o=0;o<=tmp;o++) 37 f[i+1][o+j]=max(f[i+1][o+j],f[i][o]+now); 38 } 39 } 40 int mx=0; 41 for(int i=0;i<=p;i++)mx=max(mx,f[n][i]); 42 printf("Case #%d: %d\n",t,mx); 43 } 44 return 0; 45 } 46 /**/
Workout
题意:给n(1e5)个正整数,在其中插入k个正整数,使得相邻两数之差绝对值的最大值最小,输出这个值是多少。
思路:发现如果k个数可以做到,k+1个数也可以做到,具有单调性,不妨二分答案,判断过程记录每两个数之间至少插入数的个数。需要注意我的写法中二分部分对于判断0时会出现问题,所以二分下限设成了1,0的情况只能是所有数字都相同的情况,特殊判断即可。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0;int f=1;char ch=getchar(); 6 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 8 } 9 void lrd(LL &x){ 10 x=0;int f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 13 } 14 const int INF=1e9; 15 const LL LINF=1e18; 16 const int N=1e5+10; 17 using namespace std; 18 int T; 19 int n,k,a[N]; 20 bool check(int x){ 21 int now=k; 22 for(int i=1;i<n;i++){ 23 int tmp1=a[i+1]-a[i]; 24 int tmp2=(tmp1+x-1)/x; 25 now-=tmp2-1; 26 if(now < 0)return 0; 27 } 28 return 1; 29 } 30 int main(){ 31 // freopen("in.txt","r",stdin); 32 rd(T); 33 for(int t=1;t<=T;t++){ 34 rd(n);rd(k); 35 for(int i=1;i<=n;i++)rd(a[i]); 36 int l=1,r=1e9; 37 while(l != r){ 38 int mid=l+r>>1; 39 if(check(mid))r=mid; 40 else l=mid+1; 41 } 42 bool flg=0; 43 for(int i=1;i<n;i++)if(a[i]!=a[i+1])flg=1; 44 if(!flg)l=0; 45 printf("Case #%d: %d\n",t,l); 46 } 47 return 0; 48 } 49 /**/
Bundling
题意:n(1e5)个字符串,每k(n%k==0)个分为一组,每组权值为组内元素最大公共前缀的长度,求所有组权值和的最大值是多少。
思路:trie树上dfs,一旦当前点子树大小超过了k就将这k个分为一组,贪心即可。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0;int f=1;char ch=getchar(); 6 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 8 } 9 void lrd(LL &x){ 10 x=0;int f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f; 13 } 14 const int INF=1e9; 15 const LL LINF=1e18; 16 const int N=1e5+10; 17 using namespace std; 18 int T,n,k,ans; 19 int ch[N*20][26],tot,siz[N*20],dep[N*20]; 20 string s; 21 void clear(){ 22 for(int i=0;i<=tot;i++){ 23 siz[i]=0;dep[i]=0; 24 for(int j=0;j<26;j++) 25 ch[i][j]=0; 26 } 27 tot=0;ans=0; 28 } 29 void insert(string s){ 30 int len=s.size(),now=0; 31 for(int i=0;i<len;i++){ 32 if(!ch[now][s[i]-'A'])ch[now][s[i]-'A']=++tot; 33 now=ch[now][s[i]-'A']; 34 } 35 siz[now]++; 36 } 37 void dfs(int x){ 38 for(int i=0;i<26;i++){ 39 if(!ch[x][i])continue; 40 dep[ch[x][i]]=dep[x]+1; 41 dfs(ch[x][i]); 42 siz[x]+=siz[ch[x][i]]; 43 if(siz[x] >= k)ans+=dep[x]*(siz[x]/k),siz[x]%=k; 44 } 45 if(siz[x] >= k)ans+=dep[x]*(siz[x]/k),siz[x]%=k; 46 } 47 int main(){ 48 // freopen("in.txt","r",stdin); 49 rd(T); 50 for(int t=1;t<=T;t++){ 51 rd(n);rd(k);clear(); 52 for(int i=1;i<=n;i++){ 53 cin>>s; 54 insert(s); 55 } 56 dfs(0); 57 printf("Case #%d: %d\n",t,ans); 58 } 59 return 0; 60 } 61 /**/