A.两端1中间有几个0
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
typedef long long ll;
const int N=2e5+9;
int a[N];
inline void lan(){
int n;
cin>>n;
ll cnt1=0;
for(int i=1;i<=n;i++){
cin>>a[i];
cnt1+=(a[i]==1);
}
ll ans=0;
bool ok=true;
for(int i=1;i<=n;i++){
if(!cnt1){
break;
}
if(a[i]==1 && ok){
cnt1--;
ok=false;
}else if(!ok && !a[i]){
ans++;
}else if(!ok && a[i]==1){
cnt1--;
}
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int q;
cin>>q;
while(q--){
lan();
}
return 0;
}
B.记得开ll,看数组大小
贪心从最近的开始打,前缀和思想
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+9;//数组
const int INF=1e9;
struct node{
ll hp,x;
}a[N];
inline void lan(){
ll n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i].hp;
}
for(int i=1;i<=n;i++){
cin>>a[i].x;
a[i].x=abs(a[i].x);//预处理
}
sort(a+1,a+1+n,[](const node a,const node b){
return a.x<b.x;
});
ll cur=0;
for(int i=1;i<=n;i++){
cur+=a[i].hp;
if(cur>a[i].x*k){
cout<<"NO"<<'\n';
return;
}
}
cout<<"YES"<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int q;
cin>>q;
while(q--){
lan();
}
return 0;
}
C.
2222->1133
1111x->2222(x-4), if x>4 yes, else no
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
typedef long long ll;
const int N=3e5+9;
ll a[N],prefix[N],c[N];
bool query(int l,int r){
if(l==r){
return false;
}
ll ans=c[r]-c[l-1];
ll res=prefix[r]-prefix[l-1];
if(ans>res){
return false;
}
return true;
}
inline void lan(){
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]--;
}
for(int i=1;i<=n;i++){
prefix[i]=a[i]+prefix[i-1];
c[i]=c[i-1]+(a[i]==0);
}
while(q--){
int l,r;
cin>>l>>r;
if(query(l,r)){
cout<<"YES"<<'\n';
}else{
cout<<"NO"<<'\n';
}
}
cout<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int q;
cin>>q;
while(q--){
lan();
}
return 0;
}
D.
预处理数字不同的位置
前缀和二分
#include<bits/stdc++.h>
#define INF (1ll<<60)
using namespace std;
typedef long long ll;
const int N=3e5+9;
ll a[N],prefix[N],ans[N],l[N];
ll check(int x,int i){
if(x<=0){//边界
return false;
}
if(x>l[i-1]){//说明x->i-1都是相同的数字
return false;
}
if(prefix[i-1]-prefix[x-1]>a[i]){//区间和大于a[i]
return true;
}
return false;
}
inline void lan(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
ans[i]=INF;//初始化
}
for(int i=1;i<=n;i++){
l[i]=0;
}
for(int i=1;i<=n;i++){
prefix[i]=prefix[i-1]+a[i];//前缀和
if(a[i]==a[i-1]){//预处理数字不同的位置
l[i]=l[i-1];
}else{
l[i]=i-1;
}
}
//从左边吃
for(int i=1;i<=n;i++){
if(a[i]<a[i-1]){
ans[i]=1;//一下就被吃
continue;
}
//二分找最近
ll left=1;
ll right=l[i-1];
while(left<=right){
ll mid=(left+right)>>1;
if(check(mid,i)){
left=mid+1;
}else{
right=mid-1;
}
}
if(check(right,i)){
ans[i]=min(ans[i],i-right);
}else if(check(left,i)){
ans[i]=min(ans[i],i-left);
}
}
reverse(a+1,a+1+n);
//从右边吃
for(int i=1;i<=n;i++){
l[i]=0;
}
for(int i=1;i<=n;i++){
prefix[i]=prefix[i-1]+a[i];
if(a[i]==a[i-1]){
l[i]=l[i-1];
}else{
l[i]=i-1;
}
}
for(int i=1;i<=n;i++){
if(a[i]<a[i-1]){
ans[n-i+1]=1;
continue;
}
ll left=1;
ll right=i-1;
while(left<=right){
ll mid=(left+right)>>1;
if(check(mid,i)){
left=mid+1;
}else{
right=mid-1;
}
}
if(check(right,i)){
ans[n-i+1]=min(ans[n-i+1],i-right);
}else if(check(left,i)){
ans[n-i+1]=min(ans[n-i+1],i-left);
}
}
for(int i=1;i<=n;i++){
cout<<(ans[i]==INF?-1:ans[i])<<" ";
}
cout<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int q;
cin>>q;
while(q--){
lan();
}
return 0;
}