这场开局不顺。。A题都不会做。。。B题一直不知道他只能用2,3,5。。。然后就拙计。好在最后4题都是1A没有fst勉强前50。。E题最后十分钟写了乱交也没A,事实上有很多bug赛后才A的。
C:
题意:有三种材料做汉堡。他手头上已经有一些材料,同时他有一定的现金可以去买材料。求最多能做几个汉堡。
思路:二分答案
code:
#include <algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <string> #include <math.h> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; #define N 100010 #define ALL(x) x.begin(),x.end() #define CLR(x,a) memset(x,a,sizeof(x)) typedef long long ll; typedef pair<int,int> PI; const int INF = 0x3fffffff; const int MOD = 100000007; const double EPS = 1e-7; char s[N]; int cnt[16]; int p[16]; int need[16]; ll money; bool check(ll num) { ll tot=0; for(int i=0;i<3;i++){ tot+=1ll*max(num*need[i]-cnt[i],0ll)*p[i]; } return tot<=money; } int main() { int a,b; scanf("%s",s); for(int i=0;i<3;i++) scanf("%d",&cnt[i]); for(int i=0;i<3;i++) scanf("%d",&p[i]); for(int i=0;s[i];i++){ if(s[i]=='B') need[0]++; else if(s[i]=='S') need[1]++; else need[2]++; } scanf("%I64d",&money); ll l=0, r=money+1000; while(l<r){ ll mid=(l+r)>>1; if(check(mid)) l=mid+1; else r=mid; } printf("%I64d\n",r-1); return 0; }
D:
题意:给你一层一层的水盆,从上往下,水满了会流到下面的水盆里。可以给某个水盆加水,同时也会询问某个水盆当前水的体积。注意一下,水盆的体积不一定递增,即便下面的水盆比上面的小,也能接到上面流下来的水。
思路:如果某个水盆装满了,那上面流下的水只会经过它再流到下面没满的水盆里。所以我们可以用链表维护,把满的水盆删掉。每个点最多被删一次,复杂度O(n)
code:
#include <algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <string> #include <math.h> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; #define N 200010 #define ALL(x) x.begin(),x.end() #define CLR(x,a) memset(x,a,sizeof(x)) typedef long long ll; typedef pair<int,int> PI; const int INF = 0x3fffffff; const int MOD = 100000007; const double EPS = 1e-7; int n,r[N]; bool vis[N]; ll vol[N],a[N],x; void init() { for(int i=1;i<=n;i++) r[i]=i+1; CLR(vis,true); } int next(int i) { return vis[i] ? i : (r[i]=next(r[i])); } void erase(int s,int t) { s=next(s); while(s<t){ ll Min=min(vol[s],x); vol[s]-=Min; x-=Min; if(!vol[s]) vis[s]=false; else return ; if(!x) return ; s=next(r[s]); } } int main() { int m; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%I64d",&vol[i]); a[i]=vol[i]; } init(); scanf("%d",&m); int op,p; while(m--){ scanf("%d%d",&op,&p); if(op==1){ scanf("%I64d",&x); erase(p,n+1); }else{ printf("%I64d\n",a[p]-vol[p]); } } return 0; }
E:
题意:n个站点,去掉一些,剩下k个站点。使得k个站点两两的距离和最小。
思路:排序后,答案显然是连续的k个站点。至于是哪连续k个,两个指针扫一下就好了,具体看代码。
比赛的时候排序完了,没有记录原始的位置,赛后才发现。。。
code:
#include <algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <string> #include <math.h> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; #define N 300010 #define ALL(x) x.begin(),x.end() #define CLR(x,a) memset(x,a,sizeof(x)) typedef long long ll; typedef pair<int,int> PI; const int INF = 0x3fffffff; const int MOD = 100000007; const double EPS = 1e-7; pair<ll,int> a[N]; int main() { int n,m; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%I64d",&a[i].first); a[i].second=i; } sort(a+1,a+n+1); scanf("%d",&m); ll ans=0,sum=0,l=1; for(int i=1;i<=m;i++){ ans+=(i-1)*a[i].first-sum; sum+=a[i].first; } ll now=ans; for(int i=m+1,j=1;i<=n;i++,j++){ sum-=a[j].first; now+=(m-1)*a[i].first-sum - (sum-(m-1)*a[j].first); if(now<ans){ ans=now; l=j+1; } sum+=a[i].first; } for(int i=l;i<=l+m-1;i++) printf("%d ",a[i].second); puts(""); return 0; }