A. Benches
题目大意:有n个桶,第i个桶初始有a[i]个球,还有m个球要放到桶里,问你放入后所有桶中装球数量的最大值所可能的最大,最小值
解法:首先我们找到初始最大值,最大可能就是初始最大+m,而最小则是先试着将所有桶的球数都增加到初始最大,然后再平均的去放.
#include<cstdio> #include<algorithm> using namespace std; int a[105]; int main(){ int n,m,maxx=0,s=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); maxx=max(a[i],maxx); } for(int i=1;i<=n;++i) s+=maxx-a[i]; if(s>=m) printf("%d ",maxx); else printf("%d ",maxx+(m-s+n-1)/n); printf("%d",m+maxx); return 0; }
B. Vitamins
#include<cstdio> #include<iostream> #include<string> #include<algorithm> using namespace std; const int N=1005; struct X{ int c; string a; bool operator<(const X A)const{ if(a!=A.a) return a<A.a; return c<A.c; } }x[N]; int s=1,ans=1e9,to[8]; void dfs(int a,int ac){ if(a==s+1){ if(to[0]&&to[1]&&to[2]) ans=min(ans,ac); return; } dfs(a+1,ac); for(int i=0;i<x[a].a.size();++i) ++to[x[a].a[i]-'A']; dfs(a+1,ac+x[a].c); for(int i=0;i<x[a].a.size();++i) --to[x[a].a[i]-'A']; } int main(){ freopen("a.in","r",stdin); int n; cin>>n; for(int i=1;i<=n;++i){ cin>>x[i].c>>x[i].a; sort(x[i].a.begin(),x[i].a.end()); } sort(x+1,x+n+1); for(int i=2;i<=n;++i) if(x[i].a!=x[i-1].a) x[++s]=x[i]; dfs(1,0); if(ans!=1000000000) printf("%d",ans); else printf("-1"); return 0; }
D. Petya and Array
题目大意:给你一段长度为n的序列,问它有多少个子序列的元素总和小于t(序列内的元素和t都有可能是负数)
这个问题可以进行转化,首先设原序列为a[i],前缀和为s[i];
对于每存在一个元素总和为t的子序列,就意味着存在s[r]-s[l-1]<t;
所以我们只要找出在s中有多少个数对满足靠后的与靠前的差小于t
然后这个求解方法很类似于树状数组求逆序对,只不过统计时有一些特殊的处理
首先我们把所有数排序,然后在循环的时候设两个变量i,j,i表示当前在数对中作为靠后的那个数,j表示最后一个不满足s[i]-s[ij]<t的数。
每次把这次的i能够新加入的j根据j这个元素在s[]中原本的位置在树状数组+1,
对于含i数对的数量就是i的位置前在树状数组的总和,
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int N=200005; ll t,ans; struct X{ ll a; int wz; bool operator<(const X &A)const{ if(a!=A.a) return a<A.a; else return wz<A.wz; } }x[N]; int b[N],n; void xg(int c){ for(;c<=n;c+=c&-c) ++b[c]; } ll xw(int c){ ll re=0; for(;c;c-=c&-c) re+=b[c]; return re; } int main(){ scanf("%d%lld",&n,&t); ++n; x[1].wz=1; for(int i=2;i<=n;++i){ scanf("%lld",&x[i].a); x[i].a+=x[i-1].a; x[i].wz=i; } sort(x+1,x+n+1); for(int i=1,j=1;i<=n;++i){ for(;j<=n&&x[j].a+t<=x[i].a;++j) xg(x[j].wz); ans+=xw(x[i].wz-1); } printf("%lld",(ll)(n-1)*n/2-ans); return 0; }