第二次,三道题,剩下的回学校再补,总结:还是需要多练习
A:让数列里所有的1都挨在一起,可以看出,相邻 1 之间有多少个 0 就需要操作几次,特判:当只有一个 1 或者原本全是 1 就输出 0;
void solve(){ cin>>n; int top1=0,top2=0,cnt=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(int i=1;i<=n;i++){ cin>>x; if(x==0) a[++top1]=i;//记录0的位置 if(x==1) b[++top2]=i;//记录1的位置 } if(top1==0 || top2==1){ cout<<"0"<<"\n"; return ; } for(int i=2;i<=top2;i++){ if(b[i]-b[i-1]>1){ cnt+=(b[i]-b[i-1]-1); } } cout<<cnt<<"\n"; }
B:贪心,先射击离自己最近的怪物,处理负数坐标:先按照绝对值排序,然后把负坐标的距离利用abs变成正的
ll t,n,k; struct node{ ll life,dis; }a[maxn]; bool cmp(node aa,node bb){ return abs(aa.dis)<abs(bb.dis); } void solve(){ cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i].life; for(int i=1;i<=n;i++) cin>>a[i].dis; sort(a+1,a+1+n,cmp); ll m=0; for(int i=1;i<=n;i++){ m+=a[i].life; a[i].dis=abs(a[i].dis); if(m>k*a[i].dis){ cout<<"NO"<<endl; return ; } } cout<<"YES"<<endl; }
C:由题意可以分析,数列元素都要大于 0 ,所以如果数列中的元素等于 1 ,那么肯定不能减 1,只能加 1 ,例如 1 1 2,可以变成 1 2 1 ,2 1 1 ,虽然和相同,但元素依然没变,所以是违法的。
由此可以得出,如果所有 1 的数量大于所有非 1 的数字可以减到 1 的次数总和,那么就是非法的,如果所有 1 的数量小于所有非 1 的数字可以减到 1 的次数的总和,那么就是合法的
例如 1 1 1 3 是非法的,因为所有 1 只能 加 1 ,3减到 1 只能减两次,
1 1 1 4 是合法的,操作之后是 2 2 2 1
用前缀和数组 num 记录数列中 1 的个数 ,数组 b 记录非 1 减到 1 的次数总和
ll a[maxn],b[maxn],num[maxn]; void solve(){ ll n,k; cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i]; a[i]--; // 减1表示最大的变化次数 num[i]=num[i-1]+(a[i]==0);//1看作1,非1看作0 b[i]=b[i-1]+a[i]; //每个数字的最大变化次数 } while(k--){ int l,r; cin>>l>>r; ll x=num[r]-num[l-1]; //1的数量 ll sum=b[r]-b[l-1]; // 非1的数字最大变化次数 if(x>sum || l==r) cout<<"NO"<<"\n"; else cout<<"YES"<<"\n"; } }
希望下次能写出A B C D ,再接再厉了!
标签:Educational,Rated,int,ll,Codeforces,次数,num,maxn,dis From: https://www.cnblogs.com/accbulb/p/18030932