地址:https://codeforces.com/contest/1165
思路:后x位中,其中只有后第y+1位为1,其余全是0才是合法,因此根据这个来判断后x位不合法的个数即可
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,x,y;
string str;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>x>>y>>str;
char ch;
int res=0;
for(int i=1;i<=x;++i)
{
ch=str[n-i];
if(i!=y+1){
if(ch=='1') ++res;
}else if(i==y+1){
if(ch=='0') ++res;
}
}
cout<<res<<endl;
return 0;
}
思路:求 l从1开始 a[i]>=l的最大l ,贪心,由小到大排序,然后每次用最小的a[i]来满足条件即可
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX_N=2e5+5;
int n,x,y;
int a[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;++i)
cin>>a[i];
sort(a,a+n);
int res=0;
for(int i=0;i<n;++i)
if(a[i]>res) ++res;
cout<<res<<endl;
return 0;
}
思路:直接贪心,遍历str,同时记录ch=str[i-1]的位置奇偶性p,与str[i]比较,若当前为奇数p=1,且ch==str[i]则去掉str[i]即可,
最后若剩下的个数为奇数个,则在去掉末尾的一个即可
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX_N=2e5+5;
int n;
string str;
bool boo[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>str;
int res=0,p=1;
char ch=str[0];
for(int i=1;i<n;++i)
if(p&&ch==str[i]){
boo[i]=true;
++res;
}else{
ch=str[i];
p=(p+1)%2;
}
if((n-res)%2){
++res;
for(int i=n-1;i>=0;--i)
if(!boo[i]){
boo[i]=true; break;
}
}
cout<<res<<endl;
for(int i=0;i<n;++i)
if(!boo[i]) cout<<str[i];
cout<<endl;
return 0;
}
思路:将a[i]由小到大排序,因子都是左右两两成对的,则ans=a[0]*a[n-1],在遍历ans的因子 i [2,sqrt(ans)],判断 ans的所有因子是否在a[i]中,若不在则 ans=-1,最后在判断 a[i]中是否有多余的数 a[i]*a[n-i-1]!=ans 若有则 ans=-1.
Code:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int MAX_N=3e2+5;
int n,T;
LL a[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;++i)
cin>>a[i];
sort(a,a+n);
LL ans=a[0]*a[n-1];
LL qn=sqrt(ans);
int l=0;
for(int i=2;i<=qn;++i)
if(ans%i==0){
if(a[l]!=i||a[l]*a[n-l-1]!=ans){
ans=-1; break;
}
++l;
}
qn=(n+1)/2;
for(int i=l;i<qn;++i)
if(a[i]*a[n-i-1]!=ans){
ans=-1; break;
}
cout<<ans<<endl;
}
return 0;
}
E. Two Arrays and Sum of Functions
思路:取n=4,计算ans可以发现,每个a[i] (i=[0,n-1])会计算 (i+1)*(n-i)遍,那么可以将 a[i]*=(i+1)*(n-i),这样ans就转化为求 sum{a[i]*b[i]}的最小值了。
而b[i]可以任意排序,那么最小值就为a[i]的第k小值*b[i]的第k大值。因此将 a[i],b[i]分别由小到大排序,ans=sum{a[i]*b[n-i-1]}%MOD即可
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX_N=2e5+5;
const LL MOD=(LL)998244353;
int n;
LL a[MAX_N],b[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;++i)
cin>>a[i];
for(int i=0;i<n;++i)
cin>>b[i];
for(int i=0;i<n;++i)
a[i]=a[i]*(i+1)*(LL)(n-i);
sort(a,a+n);
sort(b,b+n);
LL ans=0;
for(int i=0;i<n;++i)
ans=(ans+a[i]%MOD*b[n-i-1]%MOD)%MOD;
cout<<ans<<endl;
return 0;
}
F2. Microtransactions (hard version)
思路:二分查找+贪心
二分答案h, 而对于 ki ,用pair d{di,ki}保存ki能够打折且di<h的最大距离 di,对d由小到大排序,遍历d[i],利用贪心思路,将所有的钱用来买最后打折的ki,同时记录买完后剩下的钱S或不能够打折的数量Sum,
当前di<=h且没有打折商品时,计算购买天数ans的值,但di>h时,计算ans的值,以及遍历后商品全部打折(没有计算ans)时ans的值,最后与二分答案h比较来更新 (l,r)即可
Code:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> pr;
const int MAX_N=2e5+5;
const int INF=1e8;
int n,m;
int a[MAX_N];
pr d[MAX_N],dd[MAX_N];
bool judge(LL h);
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;d[i].second=i,++i)
cin>>a[i];
int di,ti;
for(int i=0;i<m;++i)
{
cin>>di>>ti;
dd[i]={di,ti};
}
sort(dd,dd+m);
int l=1,r=1e7,h;
while(l<=r){
h=(l+r)/2;
if(judge(h)) r=h-1;
else l=h+1;
}
cout<<l<<endl;
return 0;
}
bool judge(LL h)
{
memset(d,0,sizeof(d));
int ti,di;
for(int i=0;i<m;++i)
{
di=dd[i].first; ti=dd[i].second;
if(di>h) break;
d[ti].first=max(d[ti].first,di);
}
LL Sum1=0;
for(int i=1;i<=n;++i)
{
d[i].second=i;
if(!d[i].first){
d[i].first=INF;
Sum1+=a[i];
}
}
sort(d+1,d+n+1);
bool boo=true;
int x;
LL ans=-1,S=0,Sum=0,l=0;
for(int i=1;i<=n;++i)
{
if(d[i].first<=h){
if(d[i].first!=INF){
S+=d[i].first-l; l=d[i].first;
x=d[i].second;
if(S>a[x]){
S-=a[x];
}else{
Sum+=a[x]-S; S=0;
}
}else{
if(S<=Sum*2+Sum1*2){
Sum=Sum*2+Sum1*2;
ans=l+Sum-S;
}else{
ans=h;
}
break;
}
}else{
for(int j=i;j<=n;++j)
if(d[j].first!=INF) Sum+=a[j];
else break;
Sum=Sum*2+Sum1*2;
ans=l+Sum-S;
break;
}
}
if(ans==-1){
ans=l+Sum*2-S;
}
if(ans>h) boo=false;
return boo;
}