Codeforces Round #727 (Div. 2)
闲话:打完省赛打cf,很不在状态地硬撑,wa和t了几次挺傻的地方,d题五分钟云出思路脑抽了调不出来。最后c还fst了。可以算的我拿去while累加,真的是傻了。
A. Contest Start
题意
n个人参加比赛,每个人开始的时间呈首项x公差x的等差数列,每个人持续时间都是t,当一个人结束时他的贡献等于此时正在比赛或者开始比赛的人。要求总的贡献和。
题解
线性的覆盖问题。
首先t是覆盖长度,特判t超过n*x。
然后统计合理覆盖的部分,即1~k,再计算k+1 ~ n部分。
code
int main()
{
ll k;cin>>k;
while(k--){
ll n,x,t;cin>>n>>x>>t;
ll ans=0;
ll maxn=n*x;
if(t>=maxn){
cout<<n*(n-1)/2<<'\n';
//cout<<"debug:*\n";
continue;
}
ll p=0;
p=(maxn-t)/x;
while(p<=(n-1)&&p*x+t<=n*x)p++;
if(p*x+t>n*x)p--;
ll evr=t/x;
ans+=p*evr;
ll res=n-p;
if(res>1){
ans+=res*(res-1)/2;
}
//cout<<"debug:"<<p<<'\n';
cout<<ans<<'\n';
}
return 0;
}
补充
感谢@yueshehanjiang的补充,思路差不多,代码很简洁优美。
#define ll long long
using namespace std;
const int N = 1e6 + 10 , M = 1010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int main()
{
int k ;
cin >> k ;
while(k--)
{
ll n , x , t ;
cin >> n >> x >> t ;
ll m = t / x ;
// cout << m << "\n" ;
if(n - m >= 0) cout << (n - m) * m + (m - 1) * m / 2 << "\n" ;
else cout << n * (n - 1) / 2 << "\n" ;
}
return 0;
}
B. Love Song
题意
给一段只含小写字母的字符串,它会按照这样的方式变化:a->a,b->bb,c->ccc。以此类推。
题解
预处理加前缀和。
code
map<char,int>mp;
ll sum[100005];
int main()
{
int w=0;
for(char c='a';c<='z';c++)mp[c]=++w;
ll n;cin>>n;
ll k;cin>>k;
string s;cin>>s;
for(int i=1;i<=n;i++){
if(i==1)sum[i]=mp[s[i-1]];
else sum[i]=sum[i-1]+mp[s[i-1]];
}
//ll len=s.length();
while(k--){
ll l,r;cin>>l>>r;
ll ans=0;
ll cnt=1;
ans=sum[r]-sum[l-1];
cout<<ans<<'\n';
}
return 0;
}
C. Stable Groups
题意
数列分组,合理分组要求排序后相邻项差不超过x。现在可以添加最多k个没出现过的数,要求合理分组的最小组数。
题解
排序,存下相邻项超过x的值。
用k个数去消掉这些超过x的间隙,优先消小的。
code
ll a[200005];
int main()
{
ll n,k,x;cin>>n>>k>>x;
for(ll i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
vector<ll>b;
for(ll i=1;i<n;i++){
ll d=a[i]-a[i-1];
if(d>x)b.push_back(d);
}
ll ans=b.size()+1;
sort(b.begin(),b.end());
for(ll i=0;i<b.size();i++){
ll d=b[i];
if(ans==1)break;
if(k==0)break;
ll now=(d-1)/x;
if(now>k)break;
else k-=now,ans--;
}
cout<<ans<<'\n';
return 0;
}
D. PriceFixed
题意
n个商品,每个商品原价两块。第i个商品有两个值a[i],b[i],分别表示需要购买的数量和可以半价购买的已买商品数量。
要求用最少的钱购买所需商品。
题解
贪心一下,原价购买的尽量以b大的购买,打折购买的尽量以b小的购买。
一开始map搞,结果键值冲突了,用双指针容易一点。
code
int main()
{
ll n;cin>>n;
pair<ll,ll>a[n];
for(ll i=0;i<n;++i)cin>>a[i].second>>a[i].first;
sort(a,a+n);
ll ans=0,cnt=0;
ll l=0,r=n-1;
while(l<=r){
ll now=min(a[r].second,max(0ll,a[l].first-cnt));
cnt+=now;ans+=2ll*now;
a[r].second-=now;
if(cnt>=a[l].first){
ans+=a[l].second;cnt+=a[l].second;l++;
}
if(a[r].second==0)r--;
}
cout<<ans<<'\n';
return 0;
}