結果

問題 No.877 Range ReLU Query
ユーザー startcppstartcpp
提出日時 2019-09-06 21:57:39
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 399 ms / 2,000 ms
コード長 2,237 bytes
コンパイル時間 985 ms
コンパイル使用メモリ 81,308 KB
実行使用メモリ 15,724 KB
最終ジャッジ日時 2024-04-25 21:59:00
合計ジャッジ時間 5,938 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 3 ms
10,516 KB
testcase_01 AC 5 ms
12,228 KB
testcase_02 AC 5 ms
10,812 KB
testcase_03 AC 6 ms
10,664 KB
testcase_04 AC 3 ms
10,672 KB
testcase_05 AC 3 ms
10,968 KB
testcase_06 AC 4 ms
12,496 KB
testcase_07 AC 5 ms
10,392 KB
testcase_08 AC 6 ms
13,848 KB
testcase_09 AC 3 ms
11,380 KB
testcase_10 AC 5 ms
11,640 KB
testcase_11 AC 372 ms
15,404 KB
testcase_12 AC 321 ms
15,144 KB
testcase_13 AC 259 ms
14,996 KB
testcase_14 AC 281 ms
14,716 KB
testcase_15 AC 389 ms
15,624 KB
testcase_16 AC 377 ms
15,448 KB
testcase_17 AC 386 ms
15,724 KB
testcase_18 AC 399 ms
15,680 KB
testcase_19 AC 303 ms
15,668 KB
testcase_20 AC 344 ms
15,688 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//基本的にはa[l]+…+a[r] - x*(r-l+1)が答えだが、Σ(x-a[i]) (a[i] < x)だけ余分に答えが引かれてしまう。
//よって、a[i] < xなるi(l≦i≦r)の個数、a[i] < xなるi(l≦i≦r)についてa[i]の和、を知りたい。
//これは領域木でもできるけど実装が面倒くさいのと計算量がlog^2Nなのは嫌いなので、ソートしてセグ木で殴ります。
#include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <algorithm>
#include <functional>
#define int long long
#define rep(i, n) for(i = 0; i < n; i++)
using namespace std;

const int DEPTH = 17;
struct SegTree {
	int d[1 << (DEPTH + 1)];
	
	SegTree() {
		int i;
		rep(i, 1 << (DEPTH + 1)) { d[i] = 0; }
	}
	void add(int pos, int x) {
		pos += (1 << DEPTH) - 1;
		d[pos] += x;
		while (pos > 0) {
			pos = (pos - 1) / 2;
			d[pos] = d[pos * 2 + 1] + d[pos * 2 + 2];
		}
	}
	int sum(int l, int r, int a = 0, int b = (1 << DEPTH), int id = 0) {
		if (a >= r || b <= l) return 0;
		if (l <= a && b <= r) return d[id];
		int x = sum(l, r, a, (a + b) / 2, id * 2 + 1);
		int y = sum(l, r, (a + b) / 2, b, id * 2 + 2);
		return x + y;
	}
};

typedef pair<int, int> P;
typedef tuple<int, int, int, int> T;	//(x, l, r, id)
SegTree seg;		//まあ累積和でいいんですが
SegTree segCnt;
SegTree segSum;
int n, q;
int a[100000];
priority_queue<P, vector<P>, greater<P>> que;
T query[100000];
int ans[100000];

signed main() {
	int i;
	
	cin >> n >> q;
	rep(i, n) cin >> a[i];
	rep(i, n) que.push(P(a[i], i));
	rep(i, n) seg.add(i, a[i]);
	rep(i, q) {
		int t, l, r, x;
		cin >> t >> l >> r >> x;
		l--; r--;
		query[i] = T(x, l, r, i);
	}
	sort(query, query + q);
	
	rep(i, q) {
		int x = get<0>(query[i]);
		int l = get<1>(query[i]);
		int r = get<2>(query[i]);
		int id = get<3>(query[i]);
		
		while (!que.empty()) {
			P now = que.top();
			if (now.first >= x) break;
			int index = now.second;
			segCnt.add(index, 1);
			segSum.add(index, a[index]);
			que.pop();
		}
		
		int allSum = seg.sum(l, r + 1);
		int smallCnt = segCnt.sum(l, r + 1);
		int smallSum = segSum.sum(l, r + 1);
		
		ans[id] = allSum - x * (r + 1 - l - smallCnt) - smallSum;
	}
	
	rep(i, q) cout << ans[i] << endl;
	return 0;
}
0