kmjp's blog

競技プログラミング参加記です

Indeedなう(本選B) : A - Counting on a Triangle、B - How are you?

本選Bは本選Aより簡単でした。
http://indeednow-finalb-open.contest.atcoder.jp/tasks/indeednow_2015_finalb_a
http://indeednow-finalb-open.contest.atcoder.jp/tasks/indeednow_2015_finalb_b

A - Counting on a Triangle

整数のペアが3角形状に並んでいる。
上からN行目にはN個のペアが並んでおり、(N,1)~(N,N)が並んでいる。
ペアの重みは、2値の積だとする。
A行目からB行目に並ぶペアの重みの総和を求めよ。

x行目には(x,1)~(x,x)のペアが並んでおり、その総和は x*(1+2+...+x) = \frac{x*x*(x+1)}{2}である。
上記式をxをA~Bまで回して足せばよい。

ll mo=1000000007;

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	ll A,B;
	cin>>A>>B;
	ll tot=0;
	for(ll x=A;x<=B;x++) tot += x*x*(x+1)/2%mo;
	
	cout << tot%mo << endl;
}

B - How are you?

N人の社員がおり、各社員iは時刻S[i]に出社してT[i]に退社する。
社員iは職場にいる間に他の社員が出社するたび、その社員に挨拶をする。
各社員が何回挨拶をするかを求めよ。

累積和またはSegTreeを使い、時間範囲内の出社人数を求められるようにする。
あとはS[i]~T[i]の間に入る出社人数を求めるだけ。
以下のコードは累積和を用いている。

int N;
int S[101000],T[101000];
int num[201000],sum[201000];

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N;
	FOR(i,N) cin>>S[i]>>T[i], num[S[i]]++;
	FOR(i,2*N) sum[i+1]=sum[i]+num[i+1];
	FOR(i,N) cout<<sum[T[i]]-sum[S[i]]<<endl;
}

まとめ

若干迷う問題。ABCのC位?