読者です 読者をやめる 読者になる 読者になる

メモ

yukicoderで遊んでいる競プロゆるふわ勢

yukicoder No.178 美しいWhitespace (1)

問題はこちら
No.178 美しいWhitespace (1) - yukicoder


s[i]:=a[i]+4*b[i]、M:=max(s[i])としたとき
∀i.M≡s[i] mod2 なら Σ(M-s[i])/2 を、さもなくば-1を出力する
Σの計算はintだとオーバーフローすることに注意

int main(){
	long m=0,s=0;
	int a[1010],n,i,t;
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d%d",a+i,&t);
		a[i]+=t*4;
		if(m<a[i])m=a[i];
	}
	for(i=0;i<n;i++){
		s+=m-a[i];
		if(a[i]%2!=a[0]%2)break;
	}
	printf("%ld",i==n?s/2:-1);
	return 0;
}

この方針で短くするとこうなる

long s,m;
a[999],i,x;
main(t){
	for(gets(&t);~scanf("%d%d",&x,&t);m=x>m?x:m)a[i++]=x+=t*4;
	for(;i&~s%2;s+=m-a[--i]);
	i=!printf("%ld",s&1?-1:s/2);
}

2つ目のfor文の終了条件i>0&&n%2==0を、n%2==0⇔~n%2==-1 を利用して短く書いている
ほかは特に工夫してない

でもよく考えると配列いらなくない?

long s,m;
f,x,i;
main(t){
	for(gets(&t);~scanf("%d%d",&x,&t);){
		x+=t*4;
		s+=m-x;
		//現時点までの最大値からの差を合計に足しておく
		f+=i++?m-x&1:0;
		//ダメフラグ
		if(m<x){s+=(x-m)*i;m=x;}
		//もし最大値が更新されているなら、今までの個数i×更新量(x-m)だけ合計を増やす
	}
	s=!printf("%ld",f?-1:s/2);
}

m-xが何度も登場しているので、x+=t*4ではなくx+=4*t-mと置けばいくらか縮みそう

long s,m;
f,x,i;
main(t){
	for(gets(&t);~scanf("%d%d",&x,&t);x>0?s+=x*i,m+=x:0)s-=x+=t*4-m,f+=i++>0&x;
	s=!printf("%ld",f?-1:s/2);
}

125B

16/06/22追記
上ではフラグfには「0か非0」が入っていたので、これを「0か1」になるように f+=i++>0&x を f|=i++>0&x と書き換えれば
出力が -f|s/2 でできるようになる

long s,m;
f,x,i;
main(t){
	for(gets(&t);~scanf("%d%d",&x,&t);x>0?s+=x*i,m+=x:0)s-=x+=t*4-m,f|=i++>0&x;
	s=!printf("%ld",-f|s/2);
}
123B