Skip to content

Commit b98c19e

Browse files
authored
Merge pull request #1334 from winter-2521/StaticRangeSumWithUPB
問題追加 Static Range Sum with Upper Bound
2 parents 718e2db + 95e52e4 commit b98c19e

11 files changed

Lines changed: 395 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// https://github.com/MikeMirzayanov/testlib/blob/master/checkers/wcmp.cpp
2+
3+
// The MIT License (MIT)
4+
5+
// Copyright (c) 2015 Mike Mirzayanov
6+
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files (the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions:
13+
14+
// The above copyright notice and this permission notice shall be included in all
15+
// copies or substantial portions of the Software.
16+
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
// SOFTWARE.
24+
25+
#include "testlib.h"
26+
27+
using namespace std;
28+
29+
int main(int argc, char * argv[])
30+
{
31+
setName("compare sequences of tokens");
32+
registerTestlibCmd(argc, argv);
33+
34+
int n = 0;
35+
string j, p;
36+
37+
while (!ans.seekEof() && !ouf.seekEof())
38+
{
39+
n++;
40+
41+
ans.readWordTo(j);
42+
ouf.readWordTo(p);
43+
44+
if (j != p)
45+
quitf(_wa, "%d%s words differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), compress(j).c_str(), compress(p).c_str());
46+
}
47+
48+
if (ans.seekEof() && ouf.seekEof())
49+
{
50+
if (n == 1)
51+
quitf(_ok, "\"%s\"", compress(j).c_str());
52+
else
53+
quitf(_ok, "%d tokens", n);
54+
}
55+
else
56+
{
57+
if (ans.seekEof())
58+
quitf(_wa, "Participant output contains extra tokens");
59+
else
60+
quitf(_wa, "Unexpected EOF in the participants output");
61+
}
62+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
9 4
2+
3 2 5 2 1 4 3 2 1
3+
1 4 2
4+
2 9 3
5+
0 8 4
6+
7 7 5
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <tuple>
4+
#include "random.h"
5+
#include "../params.h"
6+
using namespace std;
7+
8+
int main(int, char* argv[]) {
9+
10+
long long seed = atoll(argv[1]);
11+
auto gen = Random(seed);
12+
13+
int N = MAX_N_Q;
14+
int Q = MAX_N_Q;
15+
printf("%d %d\n", N, Q);
16+
17+
for(int i=0; i<N; i++) {
18+
printf("%d%c", gen.uniform<int>(0, MAX_A_X), " \n"[i + 1 == N]);
19+
}
20+
21+
for(int i=0; i<Q; i++) {
22+
int l, r, x;
23+
std::tie(l, r) = gen.uniform_pair<int>(0, N);
24+
x = gen.uniform<int>(0, MAX_A_X);
25+
printf("%d %d %d\n", l, r, x);
26+
}
27+
28+
return 0;
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <tuple>
4+
#include "random.h"
5+
#include "../params.h"
6+
using namespace std;
7+
8+
int main(int, char* argv[]) {
9+
10+
long long seed = atoll(argv[1]);
11+
auto gen = Random(seed);
12+
13+
int N = gen.uniform<int>(1, MAX_N_Q);
14+
int Q = gen.uniform<int>(1, MAX_N_Q);
15+
printf("%d %d\n", N, Q);
16+
17+
for(int i=0; i<N; i++) {
18+
printf("%d%c", gen.uniform<int>(0, MAX_A_X), " \n"[i + 1 == N]);
19+
}
20+
21+
for(int i=0; i<Q; i++) {
22+
int l, r, x;
23+
std::tie(l, r) = gen.uniform_pair<int>(0, N);
24+
x = gen.uniform<int>(0, MAX_A_X);
25+
printf("%d %d %d\n", l, r, x);
26+
}
27+
28+
return 0;
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <tuple>
4+
#include "random.h"
5+
#include "../params.h"
6+
using namespace std;
7+
8+
int main(int, char* argv[]) {
9+
10+
long long seed = atoll(argv[1]);
11+
auto gen = Random(seed);
12+
13+
int N = MAX_N_Q;
14+
int Q = MAX_N_Q;
15+
printf("%d %d\n", N, Q);
16+
17+
for(int i=0; i<N; i++) {
18+
printf("%d%c", gen.uniform<int>(0, 4), " \n"[i + 1 == N]);
19+
}
20+
21+
for(int i=0; i<Q; i++) {
22+
int l, r, x;
23+
std::tie(l, r) = gen.uniform_pair<int>(0, N);
24+
x = gen.uniform<int>(1, 4);
25+
printf("%d %d %d\n", l, r, x);
26+
}
27+
28+
return 0;
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"example_00.in": "7e20623ac6a6d19290cc9f000336d03a62469a054dce9ae7748ce27751c1cdfa",
3+
"example_00.out": "07e748df7dc6a6637a6575de2acb1653e04b5bccdeb1b2e7f53bdcdf38d4da1a",
4+
"max_random_00.in": "95548bb8fdd4cbb7e3555cf509bcde0ac6f08a1736fb07c9dbccd061d7a7868c",
5+
"max_random_00.out": "ec7a69ab1f90c3a49154fe8cdaed1045f628324d86fd4f54634dce1a37da5661",
6+
"max_random_01.in": "7c5a59238d01bd2d674d93cfb19a3eeb6e7bdbcd23d0c063faee1d3e9f8b8e91",
7+
"max_random_01.out": "0b9687ec2276d4db58a7be8a3b4d621ed488b688ec4b99724839a3f29bf8b630",
8+
"max_random_02.in": "146ce8bc4767af758426cab42af063bf251db1be950882a066b67ff9e1b51a75",
9+
"max_random_02.out": "f767d2a375264b02efe91640a8efc32c5ac5ecd92f0279dfa982b49235a52925",
10+
"random_00.in": "e8c0df7ca3e37b080cb0591d2dbbd2d34d16bdd2b0a50f577f83a34ad5485b7d",
11+
"random_00.out": "6267fd63c22694ad5b30b19284f7bb39ea1e82ca3bf39548a440b52caec1dfd2",
12+
"random_01.in": "89cfda5753dc98ac2719d43eb3f808d9f02d97cdb14015f2cbd712d707ffe155",
13+
"random_01.out": "e1d487f733171abc453265682dd4b9c10033388175ef6f49b6ff50573abfe8ce",
14+
"random_02.in": "9ea18407f8759aa84fb329efb66ff7e8c8aaaa54fd5ca2fd05bf7c60e98d8508",
15+
"random_02.out": "9b72d11d3dae1a8156887faecc967fe68e3a2439c1187786ec3f01d3ce0aa3ff",
16+
"small_a_x_00.in": "5a246f2f3e35193ac0fcf090c577fe6c3d7235c8b7fbedded6152c936b7ad4c9",
17+
"small_a_x_00.out": "3aa4384b09de7f2ca1ca4ed07de39c118e4fb2a0eb20c36eec3388748d7eaf1b",
18+
"small_a_x_01.in": "4c5e86568b2bc2e26cba5f0574ed7f03d46eff3b77b6997575a88a76577cb4a3",
19+
"small_a_x_01.out": "05c6947e58a6d583a20cfd99d2bb600025888961f5b79f89aaceb454b78b505e",
20+
"small_a_x_02.in": "cf4f875caa5bfb2bd684f681a3d1a990b150bac353349f1f928a8c5f5fb50bc1",
21+
"small_a_x_02.out": "0d2b70c51edc1d52940df4b26467f9f1522d7a75676e52516fce346a21e0fbe1"
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
title = 'Static Range Sum with Upper Bound'
2+
timelimit = 5.0
3+
forum = "https://github.com/yosupo06/library-checker-problems/issues/1332"
4+
5+
[[tests]]
6+
name = "example.in"
7+
number = 1
8+
[[tests]]
9+
name = "random.cpp"
10+
number = 3
11+
[[tests]]
12+
name = "max_random.cpp"
13+
number = 3
14+
[[tests]]
15+
name = "small_a_x.cpp"
16+
number = 3
17+
18+
[[solutions]]
19+
name = "naive.cpp"
20+
allow_tle = true
21+
22+
[params]
23+
MAX_N_Q = 500_000
24+
MAX_A_X = 1_000_000_000
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include<iostream>
2+
#include<cassert>
3+
#include<vector>
4+
#include<algorithm>
5+
using namespace std;
6+
7+
template<typename T>
8+
struct MergeSortTree{
9+
int n;
10+
vector<vector<T> >dat;
11+
vector<vector<long long> >sum;
12+
13+
// 和がいらない場合 sum_mode : false にするほうがよい
14+
MergeSortTree(const vector<T>&v,bool sum_mode = true)
15+
{
16+
n=1;
17+
while(n<(int)v.size())n<<=1;
18+
dat.assign(2*n-1,vector<T>{});
19+
if(sum_mode) sum.assign(2*n-1,vector<long long>{});
20+
for(int i=0;i<(int)v.size();i++)
21+
{
22+
dat[i+n-1].push_back(v[i]);
23+
if(sum_mode){
24+
sum[i+n-1].push_back(0LL);
25+
sum[i+n-1].push_back(v[i]);
26+
}
27+
}
28+
for(int i=n-2;i>=0;i--)
29+
{
30+
dat[i].resize(dat[i*2+1].size()+dat[i*2+2].size());
31+
merge(dat[i*2+1].begin(),dat[i*2+1].end(),
32+
dat[i*2+2].begin(),dat[i*2+2].end(),
33+
dat[i].begin()
34+
);
35+
if(sum_mode){
36+
sum[i].resize(dat[i].size()+1,0LL);
37+
for(int j=0;j<(int)dat[i].size();j++)sum[i][j+1]=sum[i][j]+dat[i][j];
38+
}
39+
}
40+
}
41+
42+
//[a,b) sum(*<x)
43+
long long less_sum(int a,int b,T x,int k=0,int l=0,int r=-1)const{
44+
if(r<0)r=n;
45+
if(b<=l||r<=a)return 0LL;
46+
else if(a<=l&&r<=b)
47+
{
48+
int L=lower_bound(dat[k].begin(),dat[k].end(),x)-dat[k].begin();
49+
return sum[k][L];
50+
}
51+
else return less_sum(a,b,x,k*2+1,l,(l+r)/2)+less_sum(a,b,x,k*2+2,(l+r)/2,r);
52+
}
53+
54+
//[a,b) sum(*<=x)
55+
long long lower_sum(int a,int b,T x,int k=0,int l=0,int r=-1)const{
56+
return less_sum(a,b,x+1,k,l,r);
57+
}
58+
59+
//[a,b) count(*<x)
60+
int less_cnt(int a,int b,T x,int k=0,int l=0,int r=-1)const{
61+
if(r<0)r=n;
62+
if(b<=l||r<=a)return 0;
63+
else if(a<=l&&r<=b)return lower_bound(dat[k].begin(),dat[k].end(),x)-dat[k].begin();
64+
else return less_cnt(a,b,x,k*2+1,l,(l+r)/2)+less_cnt(a,b,x,k*2+2,(l+r)/2,r);
65+
}
66+
67+
//[a,b) count(*<=x)
68+
int lower_cnt(int a,int b,T x,int k=0,int l=0,int r=-1)const{
69+
return less_cnt(a,b,x+1,k,l,r);
70+
}
71+
72+
};
73+
74+
int main(){
75+
int n,q;
76+
scanf("%d %d",&n,&q);
77+
78+
vector<long long> a(n);
79+
for(int i = 0;i < n;i++) scanf("%lld",&a[i]);
80+
81+
MergeSortTree<long long> mst(a);
82+
83+
for(int query = 0;query < q;query++){
84+
int l,r,x;
85+
scanf("%d %d %d",&l,&r,&x);
86+
int ans_cnt = mst.lower_cnt(l,r,x);
87+
long long ans_sum = mst.lower_sum(l,r,x);
88+
printf("%d %lld\n",ans_cnt,ans_sum);
89+
}
90+
91+
return 0;
92+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include<iostream>
2+
#include<vector>
3+
using namespace std;
4+
5+
int main(){
6+
int n,q;
7+
scanf("%d %d",&n,&q);
8+
9+
vector<long long> a(n);
10+
for(int i = 0;i < n;i++) scanf("%lld",&a[i]);
11+
12+
for(int query = 0;query < q;query++){
13+
int l,r,x;
14+
scanf("%d %d %d",&l,&r,&x);
15+
int ans_cnt = 0;
16+
for(int i = l;i < r;i++){
17+
if(a[i] <= x) ans_cnt++;
18+
}
19+
long long ans_sum = 0LL;
20+
for(int i = l;i < r;i++){
21+
if(a[i] <= x) ans_sum += a[i];
22+
}
23+
printf("%d %lld\n",ans_cnt,ans_sum);
24+
}
25+
26+
return 0;
27+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## @{keyword.statement}
2+
3+
@{lang.en}
4+
Given a size $N$ sequence $a_0, a_1, \dots, a _ {N - 1}$. Process the following $Q$ queries in order:
5+
6+
- `$l$ $r$ $x$`: Print the number and the sum of the elements among $a_l,a_{l+1},...,a_{r-1}$ that are not greater than $x$
7+
@{lang.ja}
8+
長さ $N$ の数列 $a_0, a_1, \dots, a _ {N - 1}$ が与えられます。以下の $Q$ 個のクエリの答えをそれぞれ出力してください。
9+
10+
- `$l$ $r$ $x$`: $a_l,a_{l+1},...,a_{r-1}$ のうち $x$ 以下の要素の個数と総和を出力してください。
11+
@{lang.end}
12+
13+
14+
## @{keyword.constraints}
15+
16+
@{lang.en}
17+
18+
- $1 \leq N, Q \leq @{param.MAX_N_Q}$
19+
- $0 \leq a_i \leq @{param.MAX_A_X}$
20+
- $0 \leq l \leq r \leq N$
21+
- $0 \leq x \leq @{param.MAX_A_X}$
22+
23+
@{lang.ja}
24+
25+
- $1 \leq N, Q \leq @{param.MAX_N_Q}$
26+
- $0 \leq a_i \leq @{param.MAX_A_X}$
27+
- $0 \leq l \leq r \leq N$
28+
- $0 \leq x \leq @{param.MAX_A_X}$
29+
30+
@{lang.end}
31+
32+
## @{keyword.input}
33+
34+
~~~
35+
$N$ $Q$
36+
$a_0$ $a_1$ ... $a_{N - 1}$
37+
$l_0$ $r_0$ $x_0$
38+
$l_1$ $r_1$ $x_1$
39+
:
40+
$l_{Q-1}$ $r_{Q-1}$ $x_{Q-1}$
41+
~~~
42+
43+
@{example.example_00}

0 commit comments

Comments
 (0)