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;
}