Problem:
買い物 2 (Shopping 2)
問題文
JOI 商店には
N
個の商品があり，商品には
1
から
N
までの番号が付けられている．
それぞれの商品には，
定価
と
種類
が定められている．商品
i
(
1 ≦ i ≦ N
) の定価は
P
i
円である．商品の種類は
1
以上
M
以下の整数で表され，商品
i
(
1 ≦ i ≦ N
) の種類は
A
i
である．
JOI 商店は，セールを行うことにした．セールは
M
日間続き，
j
日目 (
1 ≦ j ≦ M
) には種類
j
の商品をすべて定価の半額で買うことができる．
セールの期間中に，
Q
人の客が JOI 商店を訪れた．客には
1
から
Q
までの番号が付けられている．客
k
(
1 ≦ k ≦ Q
) はセールの
T
k
日目に JOI 商店を訪れ，商品
L
k
, L
k
+1, …, R
k
を
1
つずつ買った．
セールの効果を調査するため，それぞれの客が商品を買うのにかかった金額を知りたい．
商品の情報と客の情報が与えられたとき，それぞれの客が商品を買うのにかかった金額を求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 200 000
．
1 ≦ M≦ 200 000
．
1 ≦ Q ≦ 200 000
．
2 ≦ P
i
≦ 10
9
(
1 ≦ i ≦ N
)．
P
i
は偶数である (
1 ≦ i ≦ N
)．
1 ≦ A
i
≦ M
(
1 ≦ i ≦ N
)．
1 ≦ T
k
≦ M
(
1 ≦ k ≦ Q
)．
1 ≦ L
k
≦ R
k
≦ N
(
1 ≦ k ≦ Q
)．
入力される値はすべて整数である．
入力
入力は以下の形式で与えられる．
N
M
Q
P
1
A
1
P
2
A
2
︙
P
N
A
N
T
1
L
1
R
1
T
2
L
2
R
2
︙
T
Q
L
Q
R
Q
出力
Q
行出力せよ．
k
行目 (
1 ≦ k ≦ Q
) には，客
k
が商品を買うのにかかった金額を，単位 (円) を省いて出力せよ．
入出力例
入力例 1
5 1 3
10 1
40 1
30 1
20 1
50 1
1 2 4
1 3 5
1 1 5
出力例 1
45
50
75
客
1
が商品を買うのにかかった金額は
40 ÷ 2 + 30 ÷ 2 + 20 ÷ 2 = 45
円であるため，
1
行目には
45
を出力する．
客
2
が商品を買うのにかかった金額は
30 ÷ 2 + 20 ÷ 2 + 50 ÷ 2 = 50
円であるため，
2
行目には
50
を出力する．
客
3
が商品を買うのにかかった金額は
10 ÷ 2 + 40 ÷ 2 + 30 ÷ 2 + 20 ÷ 2 + 50 ÷ 2 = 75
円であるため，
3
行目には
75
を出力する．
入力例 2
5 3 3
10 1
40 3
30 2
20 1
50 3
1 2 4
3 3 5
2 1 5
出力例 2
80
75
135
客
1
が商品を買うのにかかった金額は
40 + 30 + 20 ÷ 2 = 80
円であるため，
1
行目には
80
を出力する．
客
2
が商品を買うのにかかった金額は
30 + 20 + 50 ÷ 2 = 75
円であるため，
2
行目には
75
を出力する．
客
3
が商品を買うのにかかった金額は
10 + 40 + 30 ÷ 2 + 20 + 50 = 135
円であるため，
3
行目には
135
を出力する．
入力例 3
5 5 3
50 2
70 4
20 5
30 1
10 3
4 2 4
5 1 5
2 3 4
出力例 3
85
170
50
入力例 4
10 5 4
2 1
2 5
2 4
2 3
2 4
2 2
2 2
2 4
2 2
2 1
3 2 7
1 1 7
2 1 10
5 5 8
出力例 4
11
13
17
8
入力例 5
10 10 10
741703628 7
231838922 5
920286164 3
763741914 5
246151406 7
54109256 1
966457488 5
441379880 10
458514202 2
224373612 1
5 5 10
2 2 7
1 9 9
1 3 4
9 4 6
1 1 7
9 4 7
4 8 8
7 5 9
1 4 5
出力例 5
1907757100
3182585150
458514202
1684028078
1064002576
3897234150
2030460064
441379880
2043536529
1009893320
情報オリンピック日本委員会
作 『第 23 回日本情報オリンピック (JOI 2023/2024) 二次予選競技課題』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m, q;
    cin >> n >> m >> q;

    vector<long long> P(n + 1, 0);
    vector<int> A(n + 1);
    vector<vector<long long>> prefix_by_type(m + 1, vector<long long>(n + 1, 0));

    for (int i = 1; i <= n; i++) {
        long long w;
        int t;
        cin >> w >> t;
        A[i] = t;
        P[i] = P[i - 1] + w;
        for (int k = 1; k <= m; k++) {
            prefix_by_type[k][i] = prefix_by_type[k][i - 1] + ((k == t) ? w / 2 : 0);
        }
    }

    while (q--) {
        int t, l, r;
        cin >> t >> l >> r;
        long long minus = prefix_by_type[t][r] - prefix_by_type[t][l - 1];
        long long ans = P[r] - P[l - 1] - minus;
        cout << ans << "\n";
    }
}
accuracy: 0.3380281690140845
time_ms: 70
memory_kb: 34500
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
using namespace std;
int N, M, Q;

long long A[200010];
long long P[200010];
long long T[200010], L[200010], R[200010];
long long S[200010], ans[200010], ans2[200010];



int main()
{
    cin >> N >> M >> Q;
    vector<vector<long long >> vec(M + 1, vector<long long >(N + 1));
    for (int i = 1; i <= N; i++)
        cin >> P[i] >> A[i];
    
    for (int i = 1; i <= N; i++)
        S[i] += S[i - 1] + P[i];
    
    for (int i = 1; i <= Q; i++) 
        cin >> T[i] >> L[i] >> R[i];
        
    for (int i = 1; i <= Q; i++)
        ans[i] = S[R[i]] - S[L[i] - 1];
        
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (i == A[j])
                vec.at(i).at(j) = P[j];
        }
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            vec.at(i).at(j) += vec.at(i).at(j - 1);
        }
    }
    
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= Q; j++) {
            if (T[j]== i)
                ans2[j] = vec.at(i).at(R[j]) - vec.at(i).at(L[j] - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++)
        cout << ans[i] - ans2[i] / 2 << endl;
    
    return 0;

}
accuracy: 0.3380281690140845
time_ms: 290
memory_kb: 44672
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
using namespace std;
int N, M, Q;

long long A[200010];
long long P[200010];
long long T[200010], L[200010], R[200010];
long long S[200010], ans[200010], ans2[200010];



int main()
{
    cin >> N >> M >> Q;
    vector<vector<long long >> vec(M + 1, vector<long long >(N + 10));
    for (int i = 1; i <= N; i++)
        cin >> P[i] >> A[i];
    
    for (int i = 1; i <= N; i++)
        S[i] += S[i - 1] + P[i];
    
    for (int i = 1; i <= Q; i++) 
        cin >> T[i] >> L[i] >> R[i];
        
    for (int i = 1; i <= Q; i++)
        ans[i] = S[R[i]] - S[L[i] - 1];
        
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (i == A[j])
                vec.at(i).at(j) = P[j];
        }
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            vec.at(i).at(j) += vec.at(i).at(j - 1);
        }
    }
    
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= Q; j++) {
            if (T[j]== i)
                ans2[j] = vec.at(i).at(R[j]) - vec.at(i).at(L[j] - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++)
        cout << ans[i] - ans2[i] / 2 << endl;
    
    return 0;

}
accuracy: 0.3380281690140845
time_ms: 290
memory_kb: 44952
final_rank: 13

code_snippet: #include <iostream>
#include <vector>
using namespace std;
int N, M, Q;

long long A[200010];
long long P[200010];
long long T[200010], L[200010], R[200010];
long long S[200010], ans[200010], ans2[200010];



int main()
{
    cin >> N >> M >> Q;
    vector<vector<long long >> vec(M + 1, vector<long long >(N + 10));
    for (int i = 1; i <= N; i++)
        cin >> P[i] >> A[i];
    
    for (int i = 1; i <= N; i++)
        S[i] += S[i - 1] + P[i];
    
    for (int i = 1; i <= Q; i++) 
        cin >> T[i] >> L[i] >> R[i];
        
    for (int i = 1; i <= Q; i++)
        ans[i] = S[R[i]] - S[L[i] - 1];
        
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (i == A[j])
                vec.at(i).at(j) = P[j];
        }
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            vec.at(i).at(j) += vec.at(i).at(j - 1);
        }
    }
    
    
    for (int i = 1; i <= Q; i++) {
        for (int j = 1; j <= M; j++) {
            if (T[i]== j)
                ans2[i] = vec.at(j).at(R[i]) - vec.at(j).at(L[i] - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++)
        cout << ans[i] - ans2[i] / 2 << endl;
    
    return 0;

}
accuracy: 0.3380281690140845
time_ms: 290
memory_kb: 44952
final_rank: 13

code_snippet: #include <iostream>
#include <vector>
using namespace std;
int N, M, Q;

long long A[200010];
long long P[200010];
long long T[200010], L[200010], R[200010];
long long S[200010], ans[200010], ans2[200010];



int main()
{
    cin >> N >> M >> Q;
    vector<vector<long long >> vec(M + 1, vector<long long >(N + 10));
    for (int i = 1; i <= N; i++)
        cin >> P[i] >> A[i];
    
    for (int i = 1; i <= N; i++)
        S[i] += S[i - 1] + P[i];
    
    for (int i = 1; i <= Q; i++) 
        cin >> T[i] >> L[i] >> R[i];
        
    for (int i = 1; i <= Q; i++)
        ans[i] = S[R[i]] - S[L[i] - 1];
        
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (i == A[j])
                vec.at(i).at(j) = P[j];
        }
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            vec.at(i).at(j) += vec.at(i).at(j - 1);
        }
    }
    
    
    for (int i = 1; i <= Q; i++) {
        for (int j = 1; j <= M; j++) {
            if (T[i]== j)
                ans2[i] = vec.at(j).at(R[i]) - vec.at(j).at(L[i] - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++)
        cout << ans[i] - ans2[i] / 2 << endl;

}
accuracy: 0.3380281690140845
time_ms: 290
memory_kb: 44948
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
using namespace std;
int N, M, Q;

long long A[200010];
long long P[200010];
long long T[200010], L[200010], R[200010];
long long S[200010], ans[200010], ans2[200010];



int main()
{
    cin >> N >> M >> Q;
    vector<vector<long long >> vec(M + 1, vector<long long >(N + 1));
    for (int i = 1; i <= N; i++)
        cin >> P[i] >> A[i];
    
    for (int i = 1; i <= N; i++)
        S[i] += S[i - 1] + P[i];
    
    for (int i = 1; i <= Q; i++) 
        cin >> T[i] >> L[i] >> R[i];
        
    for (int i = 1; i <= Q; i++)
        ans[i] = S[R[i]] - S[L[i] - 1];
        
    
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (i == A[j])
                vec.at(i).at(j) += vec.at(i).at(j - 1) + P[j];
        }
    }
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            vec.at(i).at(j) += vec.at(i).at(j - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++) {
        for (int j = 1; j <= M; j++) {
            if (T[i]== j)
                ans2[i] = vec.at(j).at(R[i]) - vec.at(j).at(L[i] - 1);
        }
    }
    
    for (int i = 1; i <= Q; i++)
        cout << ans[i] - ans2[i] / 2 << endl;

}
accuracy: 0.08450704225352113
time_ms: 10
memory_kb: 44656
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M, Q;
    cin >> N >> M >> Q;

    vector<long long> P(N+1);
    vector<int> A(N+1);
    for (int i = 1; i <= N; i++) {
        cin >> P[i] >> A[i];
    }

    // 全体の累積和
    vector<long long> prefix(N+1, 0);
    for (int i = 1; i <= N; i++) {
        prefix[i] = prefix[i-1] + P[i];
    }

    // 種類ごとの位置と累積和
    vector<vector<pair<int,long long>>> kind(M+1);
    vector<long long> sumKind(M+1, 0);
    for (int i = 1; i <= N; i++) {
        int t = A[i];
        sumKind[t] += P[i];
        kind[t].push_back({i, sumKind[t]});
    }

    // クエリ処理
    for (int qi = 0; qi < Q; qi++) {
        int T, L, R;
        cin >> T >> L >> R;

        // 区間全体の合計
        long long total = prefix[R] - prefix[L-1];

        // 種類T の区間合計 (二分探索)
        auto &vec = kind[T];
        long long halfSum = 0;
        if (!vec.empty()) {
            auto itR = upper_bound(vec.begin(), vec.end(), make_pair(R, LLONG_MAX));
            auto itL = upper_bound(vec.begin(), vec.end(), make_pair(L-1, LLONG_MAX));
            if (itR != vec.begin()) {
                halfSum = prev(itR)->second;
                if (itL != vec.begin()) {
                    halfSum -= prev(itL)->second;
                }
            }
        }

        // 答え = total - halfSum/2
        cout << total - halfSum/2 << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 19760
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <bit>
#include <stack>

#pragma region

#define sz(x) (int)((x).size())

typedef long long i64;

void fast_io() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
}

void debug(const auto &... x) {
#ifdef ONLINE_JUDGE
    return;
#endif
    ((std::cerr << x << ' '), ...);
    std::cerr << '\n';
}

#define MODULUS 1000000007

#pragma endregion

class binary_indexed_tree {
public:
    binary_indexed_tree(int n) : A(n) {}

    void add(int index, i64 x) {
        if (index < 0 || index >= sz(A)) {
            return;
        }
        if (index == 0) {
            A[0] += x;
            return;
        }
        while (index < sz(A)) {
            A[index] += x;
            index += index & -index;
        }
    }

    i64 get_prefix_sum(int index) {
        if (index < 0) {
            return 0;
        }
        index = std::min(index, sz(A) - 1);
        i64 ans = A[0];
        while (index) {
            ans += A[index];
            index &= index - 1;
        }
        return ans;
    }

    i64 get_range_sum(int a, int b) {
        return get_prefix_sum(b) - get_prefix_sum(a - 1);
    }

private:
    std::vector<i64> A;
};

int N, M, Q;

std::vector<int> P;

std::vector<i64> answers;

std::vector<std::vector<int>> day_to_products;

struct visitor {
    int index;
    int L;
    int R;
};

std::map<int, std::vector<visitor>> visitors;

void input() {
    std::cin >> N >> M >> Q;
    P.resize(N);
    day_to_products.resize(M);
    for (int i = 0; i < N; ++i) {
        int day;
        std::cin >> P[i] >> day;
        --day;
        day_to_products[day].push_back(i);
    }

    answers.resize(Q);
    for (int i = 0; i < Q; ++i) {
        int T, L, R;
        std::cin >> T >> L >> R;
        --T;
        --L;
        --R;
        visitors[T].emplace_back(i, L, R);
    }
}

void solve() {
    binary_indexed_tree tree(N);
    for (int i = 0; i < N; ++i) {
        tree.add(i, P[i]);
    }
    for (int day = 0; day < M; ++day) {
        for (int p: day_to_products[day]) {
            tree.add(p, -P[p] / 2);
        }

        for (auto &v: visitors[day]) {
            answers[v.index] = tree.get_range_sum(v.L, v.R);
        }

        for (int p: day_to_products[day]) {
            tree.add(p, P[p] / 2);
        }
    }
    for (auto &x: answers) {
        std::cout << x << "\n";
    }
}

int main() {
    fast_io();
    input();
    solve();
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 38340
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <climits>

int main()
{
    int N, M, Q;
    std::cin >> N >> M >> Q;
    std::vector<long long> P(N+1);
    std::vector<long long> A(N+1);
    P[0] = 0;
    for(int i = 1; i < N+1; i++){
        std::cin >> P.at(i) >> A.at(i);
    }
    
    std::vector<long long> T(Q);
    std::vector<long long> L(Q);
    std::vector<long long> R(Q);
    for(int k = 0; k < Q; k++){
        std::cin >> T.at(k) >> L.at(k) >> R.at(k);
    }

    std::vector<long long> TOTAL(N+1);
    TOTAL.at(0) = 0;
    for(int i = 1; i < N+1; i++){
        int p = P.at(i);
        TOTAL.at(i) = p + TOTAL.at(i-1);
    }
    
    std::unordered_map<int, std::vector<std::pair<long long, long long>>> SALE;
    for(int i = 1; i < N+1; i++){
        SALE[A[i]].emplace_back(i, P[i]);
    }

    std::unordered_map<int, std::vector<long long>> SALE_TOTAL;
    for(auto &[t, vec] : SALE){
        std::sort(vec.begin(), vec.end());
        SALE_TOTAL[t].resize(vec.size() + 1, 0); // 1-index
        for(int i = 0; i < vec.size(); i++){
            SALE_TOTAL[t][i+1] = SALE_TOTAL[t][i] + vec[i].second / 2;
        }
    }

    for(int k = 0; k < Q; k++){
        auto t = T.at(k);
        auto l = L.at(k);
        auto r = R.at(k);
        long long tmp = TOTAL.at(r) - TOTAL.at(l-1);
        long long d = 0;
        if (SALE.count(t)) {
            const auto& vec = SALE[t];
            const auto& st = SALE_TOTAL[t];
            
            auto it_l = lower_bound(vec.begin(), vec.end(), std::make_pair(l, 0LL));
            auto it_r = upper_bound(vec.begin(), vec.end(), std::make_pair(r, LLONG_MAX));

            int il = it_l - vec.begin();
            int ir = it_r - vec.begin();

            d = st[ir] - st[il];
        }
        
        std::cout << (tmp - d) << std::endl;
    }
}
accuracy: 1
time_ms: 290
memory_kb: 49524
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 200005

struct Info{
	ll P;
	int type;
};

Info info[SIZE];
vector<int> V[SIZE];
vector<ll> rui[SIZE];
ll A[SIZE];

int main(){

	int N,M,numQ;
	scanf("%d %d %d",&N,&M,&numQ);

	for(int i = 1; i <= M; i++){
		rui[i].push_back(0);
	}

	for(int i = 1; i <= N; i++){

		scanf("%lld %d",&info[i].P,&info[i].type);
		V[info[i].type].push_back(i);
		rui[info[i].type].push_back(info[i].P/2);
		A[i] = info[i].P;
		A[i] += A[i-1];
	}

	for(int i = 1; i <= M; i++){
		if(V[i].size() == 0)continue;

		for(int k = 1; k < rui[i].size(); k++){
			rui[i][k] += rui[i][k-1];
		}
	}

	int T,L,R;

	for(int loop = 0; loop < numQ; loop++){

		scanf("%d %d %d",&T,&L,&R);

		if(V[T].size() == 0){

			printf("%lld\n",A[R]-A[L-1]);
			continue;
		}

		int left = lower_bound(V[T].begin(),V[T].end(),L)-V[T].begin();
		int right = upper_bound(V[T].begin(),V[T].end(),R)-V[T].begin();
		right--;

		ll ans = A[R]-A[L-1];
		ll minus = rui[T][right+1]-rui[T][left];

		printf("%lld\n",ans-minus);
	}

	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 30032
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 200005

struct Info{
	ll P;
	int type;
};

Info info[SIZE];
vector<int> V[SIZE];
vector<ll> rui[SIZE];
ll A[SIZE];

int main(){

	int N,M,numQ;
	scanf("%d %d %d",&N,&M,&numQ);

	for(int i = 1; i <= M; i++){
		rui[i].push_back(0);
	}

	for(int i = 1; i <= N; i++){

		scanf("%lld %d",&info[i].P,&info[i].type);
		V[info[i].type].push_back(i);
		rui[info[i].type].push_back(info[i].P/2);
		A[i] = info[i].P;
		A[i] += A[i-1];
	}

	for(int i = 1; i <= M; i++){
		if(V[i].size() == 0)continue;

		for(int k = 1; k < rui[i].size(); k++){
			rui[i][k] += rui[i][k-1];
		}
	}

	int T,L,R;

	for(int loop = 0; loop < numQ; loop++){

		scanf("%d %d %d",&T,&L,&R);

		if(V[T].size() == 0){

			printf("%lld\n",A[R]-A[L-1]);
			continue;
		}

		int left = lower_bound(V[T].begin(),V[T].end(),L)-V[T].begin();
		int right = upper_bound(V[T].begin(),V[T].end(),R)-V[T].begin();
		right--;

		//printf("left:%d right:%d\n",left,right);

		ll ans = A[R]-A[L-1];
		ll minus = rui[T][right+1]-rui[T][left];

		//printf("ans:%lld minus:%lld\n",ans,minus);

		printf("%lld\n",ans-minus);
	}

	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 30060
final_rank: 4

code_snippet: #include <iostream>
#include <cstdint>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	
	uint32_t N, M, Q, i;
	cin >> N >> M >> Q;
	vector<uint32_t> P(N), A(N), T(Q), L(Q), R(Q);
	for (i = 0; i != N; ++i) cin >> P[i] >> A[i];
	for (i = 0; i != Q; ++i) cin >> T[i] >> L[i] >> R[i];

	vector<uint64_t> P_csum(N + 1, 0);
	for (i = 0; i != N; ++i) P_csum[i + 1] = P_csum[i] + P[i];

	vector<vector<pair<uint32_t, uint64_t>>> discount_csum_at_day(M, vector<pair<uint32_t, uint64_t>>(1, { UINT32_MAX, 0 }));
	for (i = 0; i != N; ++i)
	{
		discount_csum_at_day[A[i] - 1].back().first = i;
		discount_csum_at_day[A[i] - 1].emplace_back(UINT32_MAX, discount_csum_at_day[A[i] - 1].back().second + (P[i] >> 1));
	}

	for (i = 0; i != Q; ++i)
	{
		const auto& now_on_sale = discount_csum_at_day[T[i] - 1];
		const auto discount = upper_bound(now_on_sale.begin(), now_on_sale.end(), pair<uint32_t, uint64_t>{ R[i] - 1, UINT64_MAX })->second - lower_bound(now_on_sale.begin(), now_on_sale.end(), pair<uint32_t, uint64_t>{ L[i] - 1, 0 })->second;
		cout << P_csum[R[i]] - P_csum[L[i] - 1] - discount << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 26004
final_rank: 2

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
    int n;
    vector<S> tree;
    segtree() : segtree(0) {}
    segtree(int n) : n(n), tree(vector<S>(n << 1, e())) {}
    segtree(const vector<S> &v) : n((int)v.size()) {
        tree.resize(n * 2);
        for (int i = 0; i < n; ++i) {
            tree[n + i] = v[i];
        }
        for (int i = n - 1; i >= 1; --i) {
            update(i);
        }
    }
    void update(int k) { tree[k] = op(tree[k << 1 | 0], tree[k << 1 | 1]); }
    S operator[](int i) { return tree[i + n]; }
    void set(int i, S x) {
        i += n;
        tree[i] = x;
        while (i >>= 1) {
            update(i);
        }
    }
    // [l,r)
    S query(int l, int r) {
        S sml = e(), smr = e();
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) sml = op(sml, tree[l++]);
            if (r & 1) smr = op(tree[--r], smr);
        }
        return op(sml, smr);
    }
};

using S = ll;
S op(S a, S b) { return a + b; }
S e() { return 0LL; }

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m, q;
    cin >> n >> m >> q;
    vector<ll> a(n), b(n);
    vector<vector<int>> v(m);
    for (int i = 0; i < n; ++i) {
        cin >> a[i] >> b[i];
        b[i] -= 1;
        v[b[i]].push_back(i);
    }
    segtree<S, op, e> seg(a);
    vector<ll> res(q);
    vector<vector<tuple<int, int, int>>> query(m);
    for (int i = 0; i < q; ++i) {
        int u;
        cin >> u;
        int l, r;
        cin >> l >> r;
        query[u - 1].push_back({l - 1, r, i});
    }
    for (int i = 0; i < m; ++i) {
        for (int j : v[i]) {
            seg.set(j, a[j] / 2);
        }
        for (auto [l, r, idx] : query[i]) {
            res[idx] = seg.query(l, r);
        }
        for (int j : v[i]) {
            seg.set(j, a[j]);
        }
    }
    for (ll i : res) {
        cout << i << '\n';
    }
}
accuracy: 1
time_ms: 130
memory_kb: 31120
final_rank: 5

code_snippet: #include<bits/stdc++.h>

#include <algorithm>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <vector>

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    segtree(int n) : segtree(std::vector<S>(n, e())) {}
    segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

using namespace atcoder;
using namespace std;

using ll=long long;
using vll=vector<ll>;
#define rep(i,s,t) for(ll i=s;i<t;i++)

ll op(ll a,ll b){return a+b;};
ll e(){return 0;};

int main(){
    ll N,M,Q;
    cin>>N>>M>>Q;
    segtree<ll,op,e> seg(N);
    vector<vll> D(M);
    rep(i,0,N){
        ll P,A;
        cin>>P>>A;
        A--;
        D[A].push_back(i);
        seg.set(i,P);
    }
    vector<vector<pair<ll,pair<ll,ll>>>> query(M);
    rep(i,0,Q){
        ll T,L,R;
        cin>>T>>L>>R;
        query[T-1].push_back({i,{L,R}});
    }
    vll AN(Q);
    rep(i,0,M){
        for(auto t:D[i]){
            seg.set(t,seg.get(t)/2);
        }
        for(auto q:query[i]){
            ll L=q.second.first;
            ll R=q.second.second;
            ll p=q.first;
            AN[p]=seg.prod(L-1,R);
        }
        for(auto t:D[i]){
            seg.set(t,seg.get(t)*2);
        }
    }
    rep(i,0,Q)cout<<AN[i]<<endl;
}
accuracy: 1
time_ms: 390
memory_kb: 30864
final_rank: 8

code_snippet: // AOJ #776
// Shopping 2 2025.1.11

#include <bits/stdc++.h>
using namespace std;

/*
  問題の制約:
    - 1 <= N, M, Q <= 200000
    - 2 <= P_i <= 10^9, かつ P_i は偶数
    - 1 <= A_i <= M
    - 1 <= T_k <= M
    - 1 <= L_k <= R_k <= N
*/

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // 入力受け取り
    long long N, M, Q;
    cin >> N >> M >> Q;

    vector<long long> P(N);
    vector<int> A(N);
    for(int i = 0; i < N; i++){
        cin >> P[i] >> A[i];
        // A[i] は 1-indexed で与えられるので，後で配列に入れるときは 0-indexed に合わせるかどうか注意
        A[i]--;  // 種類A_iを0-indexed化 (0 <= A[i] < M)
    }

    // まず「全商品の価格の累積和」を作る (1-indexed の累積和を使いたいので要注意)
    // prefAll[i] = P[0] + ... + P[i-1] ( i: 1..N )
    // ようにしておくときはサイズN+1で作る。
    vector<long long> prefAll(N+1, 0LL);
    for(int i = 0; i < N; i++){
        prefAll[i+1] = prefAll[i] + P[i];
    }

    // 種類ごとに「その種類に属する商品」の(添字,価格)を格納し，ついでに価格のみの累積和を作る
    // typePos[t] : 種類tに属する商品の"添字 i(0-indexed)"を昇順に並べる
    // typeVal[t] : その商品価格 P[i]
    // typePref[t] : typeVal[t] のprefix sum (要素数+1)
    vector<vector<int>> typePos(M);
    vector<vector<long long>> typeVal(M);
    // 入力が 1 から N の順番で与えられるので，
    // i が増加していくにつれ i は自動的に昇順になるためソート不要。
    for(int i = 0; i < N; i++){
        int t = A[i];     // 0-indexed 種類
        typePos[t].push_back(i);
        typeVal[t].push_back(P[i]);
    }

    // 各種類ごとに prefix sum を作る
    vector<vector<long long>> typePref(M);
    for(int t = 0; t < (int)M; t++){
        typePref[t].resize(typeVal[t].size()+1, 0LL);
        for(int i = 0; i < (int)typeVal[t].size(); i++){
            typePref[t][i+1] = typePref[t][i] + typeVal[t][i];
        }
    }

    // クエリ処理
    // クエリ (T_k, L_k, R_k) は 1-indexed で与えられるので注意
    // 計算式:
    //   cost = (prefAll[R_k] - prefAll[L_k - 1]) - (1/2)* ( 種類T_k の [L_k..R_k] 範囲の価格合計 )

    // 種類T_k は入力時に1-indexedなので 0-indexedに直して扱う
    // 区間 [L, R] も0-indexedで扱うには [L_k - 1, R_k - 1] にする

    while(Q--){
        long long T_k, L_k, R_k;
        cin >> T_k >> L_k >> R_k;
        T_k--;  // 種類も0-index化
        // いったん 0-index 化
        L_k--;  
        R_k--;  

        // 全商品の定価合計 (区間 [L_k, R_k])
        long long total = prefAll[R_k+1] - prefAll[L_k];

        // 種類 T_k の区間 [L_k, R_k] の合計価格を2分探索で求める
        // typePos[T_k] の中で L_k 以上の位置に初めて登場する要素 idxL
        // かつ R_k 以下の位置に最後に登場する要素 idxR を見つければよい
        //   idxL = lower_bound(pos.begin(), pos.end(), L_k)
        //   idxR = upper_bound(pos.begin(), pos.end(), R_k) - 1
        // idxL <= idxR なら区間が存在
        const auto &posVec = typePos[T_k];       // 種類T_kに該当する商品の添字リスト
        const auto &prefVec = typePref[T_k];     // その累積和

        long long sumType = 0LL;
        // lower_bound, upper_bound
        auto itL = std::lower_bound(posVec.begin(), posVec.end(), (int)L_k);
        auto itR = std::upper_bound(posVec.begin(), posVec.end(), (int)R_k);

        if(itL != posVec.end() && itR != posVec.begin()){
            // itR は区間外の一つ後ろなので itR-1 が実際の区間終端
            // ただし itL > itR-1 の場合は該当なし
            int idxL = (int)std::distance(posVec.begin(), itL);
            int idxR = (int)std::distance(posVec.begin(), itR) - 1;
            if(idxL <= idxR){
                sumType = prefVec[idxR+1] - prefVec[idxL];
            }
        }

        // 実際の支払金額 = total - sumType/2
        // (問題文より P_i は偶数なので /2 は割り切れる)
        long long ans = total - sumType / 2LL;

        cout << ans << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 39748
final_rank: 7