yukicoder No.59 鉄道の旅
問題概要
区間の和と1つの要素に値を加算減算を拘束にできればいい.
解法
BITを使った.
BITは
-区間の和
-1つ要素に値を加える
ことができるデータ構造.
今回の問題では積荷をBITで管理した. w>0の時はw以上の重さのものがk個より少なければ、その積荷を積むという処理をする.この時に、BITで管理していると、w以上のものの総和がlog(MAX_W)でもとまり、加算もlog(MAX_W)で行える。w<0の時はwがあれば-1を加算すればいい.
他の人と回答を見てると、omosa[i]などで重さiの荷物のものの個数などをメモしておくことで、sum(-w) - sum(-w - 1) = (重さwの荷物の数) の処理を代用している回答があった.
ミス
BITは実装が楽でいいですね.応用するのは難しそう. この問題はBIT使わずに、multiset使って、やっている人いたけど、TLEしてた。(n*logn)で通りそうなんだけどな.
コード
#include <iostream> #include <vector> using namespace std; typedef long long ll; #define rep(i,n) for(int i=0;i<(n);i++) //[1,n] const int MAX_W = 1000010; int bit[MAX_W + 1]; int sum(int i){//iまでの和を求める int s = 0; while(i > 0){ s += bit[i]; i -= i & -i; } return s; } void add(int i, int x){//iの値にxを加える while(i <= MAX_W){ bit[i] += x; i += i & -i; } } int main(void){ int n, k; cin >> n >> k; vector<int> w(n); rep(i, MAX_W + 1) bit[i] = 0; rep(i, n){ int w; cin >> w; if(w > 0){ if(sum(MAX_W) - sum(w - 1) < k){ add(w, 1); } }else{ if(sum(-w) - sum(-w - 1) >= 1){ add(-w, -1); } } } cout << sum(MAX_W) << endl; return 0; }