文章目录
A. A Variety of Operations
如果两个数相差是奇数,就输出-1。
如果相差是偶数,就输出2
相等就输出0
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
for( int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
if(abs(a-b)%2==1){
cout<<-1<<endl;
}
else if(a==0&&b==0){
cout<<0<<endl;
}
else if(a==b){
cout<<1<<endl;
}
else {
cout<<2<<endl;
}
}
}
Take Your Places!
先判断能不能实现,如果不能实现输出-1。
因为最终情况是奇偶相间,因此最终每个数的位置显而易见。
只需将每个数的初始位置存储起来,再计算与最终位置的距离。
#include <bits/stdc++.h>
using namespace std;
long long a[100100];
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
vector<int>odd;
int cntodd=0,cnteven=0;
for( int i=1;i<=n;i++){
cin>>a[i];
a[i]%=2;
if(a[i]==1){
odd.push_back(i);
cntodd++;
}
else {
cnteven++;
}
}
if(abs(cntodd-cnteven)>1){
cout<<-1<<endl;
continue;
}
long long res=0,res2=0;
if(cntodd==cnteven)
for( int i=0;i<odd.size();i++){
res+=abs(odd[i]-(i*2+1));
}
if(cntodd==cnteven){
for( int i=0;i<odd.size();i++){
res2+=abs(odd[i]-((i+1)*2));
}
}
else if(cntodd>cnteven){
for( int i=0;i<odd.size();i++){
res+=abs(odd[i]-(i*2+1));
}
}
else{
for( int i=0;i<odd.size();i++){
res+=abs(odd[i]-((i+1)*2));
}
}
if(cntodd==cnteven)//这里注意要分两种情况讨论122211
cout<<min(res,res2)<<endl;
else{
cout<<res<<endl;
}
}
}
C. Compressed Bracket Sequence
枚举左右区间,左右区间节点分别为i和j
使用left变量代表i节点上的左括号数量,使用other代表区间内除了left之外,未配对的左括号数量,显然,当other大于0时,当前组合的开始点不是i,因此不符合题意。
下面循环右端点j,分为以下两种情况:
- 当循环到左括号时,other+=a[ j ]
- 当循环到右括号时:分为一下几种情况:
1. 若a[ j ] < other 那么配对之后other中还存在没有配对的括号,因此ans不变,执行other -= a[j];continue;
2. 若a[ j ]==other 那么这时other中的括号正好全部配对。如果left中有配对的括号(mark!=0),那么ans++
。反之continue
3. 若a[ j ]>other 那么此时other中的括号全部配对,如果mark==1
则ans++
,而且还溢出一些右括号(此时令mark=1
)other变为0。将这些右括号与left配对ans+=min(left,remain)
并且计算left的剩余值left-=remain
如果left为负值,说明右括号有多余,此时直接break。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1010];
int main(){
int n;
cin>>n;
ll ans=0;
for( int i=1;i<=n;i++) cin>>a[i];
for( int i=1;i<=n;i+=2){
ll left=a[i],mark=0,other=0;
for( int j=i+1;j<=n;j++){
if(j%2==1){
other+=a[j];
continue;
}
if(a[j]<other) {
other-=a[j];
continue;
}
if(a[j]>=other){
if(mark!=0) ans++;
ll temp=a[j]-other;
if(temp>0) mark=1;
ans+=min(temp,left);
left-=temp;
other=0;
}
if(left<0) break;
}
// cout<<i<<" "<<ans<<endl;
}
cout<<ans<<endl;
}
D. Take a Guess
只需一个公式:a&b+a|b==a+b
利用公式将所有的数都算出来
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum[30010];
ll val[30010];
ll val2[30010];
int main(){
int n,k;
cin>>n>>k;
for( int i=1;i<=n;i++){
int OR=0,AND=0;
if(i%3!=0){
cout<<"or"<<" "<<i<<" "<<(i+1)%(n+1)+(bool)(!((i+1)%(n+1)))<<endl;
fflush(stdout);
cin>>OR;
cout<<"and"<<" "<<i<<" "<<(i+1)%(n+1)+(bool)(!((i+1)%(n+1)))<<endl;
fflush(stdout);
cin>>AND;
sum[i]=AND+OR;
}
else{
cout<<"or"<<" "<<i<<" "<<(i-2)%n<<endl;
fflush(stdout);
cin>>OR;
cout<<"and"<<" "<<i<<" "<<(i-2)%n<<endl;
fflush(stdout);
cin>>AND;
sum[i]=AND+OR;
}
}
for( int i=1;i+2<=n;i+=3){
val[i]=(sum[i]+sum[i+2]-sum[i+1])/2;
val[i+2]=(sum[i+2]-val[i]);
val[i+1]=(sum[i+1]-val[i+2]);
}
for( int i=n;i>=n-n%3+1;i--){
if(i==n)
val[i]=sum[i]-val[1];
else
val[i]=sum[i]-val[i+1];
}
for( int i=1;i<=n;i++) val2[i]=val[i];
sort(val+1,val+1+n);
cout<<"finish "<<val[k]<<endl;
}
E. Equilibrium
前缀和,线段树
详解:
问题研究的是两个数组的差值,首先将两个数组相减,这里用a[ i ] - b[ i ]
首先讨论不成立的情况:
因为每次需要选择 偶数个 数,而且第一个数必须+1,所以如果某一段的前缀和大于0,那么正数就无法消去,题设就不能成立。而且区间的前缀和必须为0,否则题设也不成立。
再讨论成立的情况:
如果问题成立,那么只需输出前缀和最小值的绝对值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 200100
struct node {
int l,r;
ll maxn;
ll minn;
}tr[N*4];
ll a[N],b[N];
ll sub[N];
void creat(int rt,int l,int r){
tr[rt].l=l,tr[rt].r=r;
if(l==r) {
tr[rt].maxn=tr[rt].minn=sub[l];
return ;
}
int mid=(l+r)/2;
creat(rt*2,l,mid);
creat(rt*2+1,mid+1,r);
tr[rt].maxn=max(tr[rt*2].maxn,tr[rt*2+1].maxn);
tr[rt].minn=min(tr[rt*2].minn,tr[rt*2+1].minn);
}
ll qmax( int rt,int L,int R){
int l=tr[rt].l,r=tr[rt].r;
if(l>=L&&r<=R) return tr[rt].maxn;
if(r<L||l>R) return -1e16;
int mid=(l+r)/2;
ll x=-1e16,y=-1e16;
if(L<=mid) x=qmax(rt*2,L,R);
if(R>mid) y=qmax(rt*2+1,L,R);
return max(x,y);
}
ll qmin( int rt,int L,int R){
int l=tr[rt].l,r=tr[rt].r;
if(l>=L&&r<=R) return tr[rt].minn;
if(r<L||l>R) return 1e16;
int mid=(l+r)/2;
ll x=1e16,y=1e16;
if(L<=mid) x=qmin(rt*2,L,R);
if(R>mid) y=qmin(rt*2+1,L,R);
return min(x,y);
}
int main(){
int n,m;
cin>>n>>m;
for( int i=1;i<=n;i++) cin>>a[i];
for( int i=1;i<=n;i++) cin>>b[i];
for( int i=1;i<=n;i++) sub[i]=a[i]-b[i];
for( int i=1;i<=n;i++) sub[i]=sub[i]+sub[i-1];
creat(1,1,n);
while( m--){
int l,r;
cin>>l>>r;
// cout<<qmax(1,l,r)<<endl;
if(sub[l-1]!=sub[r]||qmax(1,l,r)-sub[l-1]>0) {//注意这里判断两个条件
cout<<-1<<endl;
continue;
}
else{
cout<<abs(qmin(1,l,r)-sub[l-1])<<endl;
}
}
}