题目背景
又是一个无聊的下午,Wu_Mr
和 108oahnew
都有些不知道想干什么。
“想不想来点刺激的?”Wu_Mr
向 108oahnew
询问。
“啥?这可是在机房,能搞啥?”
Wu_Mr
露出不怀好意地微笑。“就是机房才刺激嘛。”
说着,她就从自己的凳子上站起来,坐到了 108oahnew
的腿上。108oahnew
的脸瞬间涨红了。
“喂,快下来,被教练看到就凉凉了。”
“别啊,这多有意思。”说着,Wu_Mr
就把脸向 108oahnew
的脸凑了过去。
“李在赣神魔?快坐回到自己的座位上去。”来自一只从门口进来的教练。
Wu_Mr
意犹未尽地坐了回去。
因为教练觉得 Wu_Mr
的行为太不好了,于是就罚 Wu_Mr
去做了一道比较难的题。
但是 Wu_Mr
毕竟是神,那种题对她来说太简单了。不过本着有福同享的原则,她把题改简单了一些给了 108oahnew
来做。
题面描述
给定一个长度为 n n n 的数列 ,有 q q q 次询问,每次给定三个数 l , r , w l,r,w l,r,w,你要求出 ∑ i = l r ⌊ w a i ⌋ \sum_{i=l}^r \left\lfloor\dfrac{w}{a_i}\right\rfloor ∑i=lr⌊aiw⌋ 的值。
部分测试点强制在线。
第一行四个数
n
,
q
,
t
y
p
,
W
n,q,typ,W
n,q,typ,W。
n
n
n 和
q
q
q 含义如题面描述,
t
y
p
typ
typ 表示是否强制在线(
0
0
0 表示不是,
1
1
1 表示是),
W
W
W 的含义如下面描述。
接下来一行 n n n 个数,第 i i i 个数表示 a i a_i ai。
接下来 q q q 行,每行三个数 l ′ , r ′ , w ′ l',r',w' l′,r′,w′。
如果 t y p = 0 typ=0 typ=0,则真实询问的 l = l ′ , r = r ′ , w = w ′ l=l',r=r',w=w' l=l′,r=r′,w=w′。
否则,真实询问的
l
,
r
,
w
l,r,w
l,r,w 由如下公式计算(其中
⊕
\oplus
⊕是异或位运算):
l
=
min
(
(
l
′
⊕
l
a
s
t
a
n
s
)
m
o
d
n
+
1
,
(
r
′
⊕
l
a
s
t
a
n
s
)
m
o
d
n
+
1
)
l=\min((l' \oplus lastans) \bmod n + 1,(r' \oplus lastans)\bmod n + 1)
l=min((l′⊕lastans)modn+1,(r′⊕lastans)modn+1)
r
=
max
(
(
l
′
⊕
l
a
s
t
a
n
s
)
m
o
d
n
+
1
,
(
r
′
⊕
l
a
s
t
a
n
s
)
m
o
d
n
+
1
)
r=\max((l' \oplus lastans) \bmod n + 1,(r' \oplus lastans)\bmod n + 1)
r=max((l′⊕lastans)modn+1,(r′⊕lastans)modn+1)
w
=
(
w
′
⊕
l
a
s
t
a
n
s
)
m
o
d
W
+
1
w=(w' \oplus lastans)\bmod W + 1
w=(w′⊕lastans)modW+1
其中 l a s t a n s lastans lastans 表示上次询问的答案(初始为 0 0 0)。
对于每个询问输出一行一个数,表示对应询问的答案。保证答案在 int 范围内(出题人懒)。
样例输入 1
10 5 0 100
17 95 5 55 61 9 62 17 25 75
4 6 1
4 10 57
8 10 51
6 8 8
3 8 67
样例输出 1
0
12
5
0
26
样例输入 2
10 5 1 100
1 3 3 1 1 9 10 9 9 9
2 10 5
6 10 57
2 4 7
2 10 12
1 10 83
样例输出 2
10
86
191
252
167
样例解释 2
真实的询问分别是:
1 3 6
1 3 52
3 5 82
2 10 80
4 7 76
对于 20 % 20 \% 20% 的数据, n ≤ 100 n \leq 100 n≤100。
对于另外 10 % 10 \% 10% 的数据, n ≤ 2000 , W ≤ 5000 n \leq 2000,W \leq 5000 n≤2000,W≤5000。
对于另外 30 % 30 \% 30% 的数据, t y p e = 0 type=0 type=0。
对于 100 % 100 \% 100% 的数据, n ≤ 1 0 5 , q ≤ 1 0 5 , W ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 n \leq 10^5,q \leq 10^5, W \leq 10^5, 1 \leq a_i \leq 10^9 n≤105,q≤105,W≤105,1≤ai≤109。
主席树是假的。。
O
(
n
n
l
o
g
n
)
=
6
e
8
O(n\sqrt nlogn)=6e8
O(nnlogn)=6e8 却是假的,未能卡过去。。
题解:
我们考虑分块。
首先,发现
⌊
w
a
i
⌋
\left\lfloor\dfrac{w}{a_i}\right\rfloor
⌊aiw⌋很像整数分块,同时注意到若我们对
a
[
i
]
a[i]
a[i] 按
n
\sqrt n
n 分块:
小于
n
\sqrt n
n 的查询时前缀和算。
大于
n
\sqrt n
n 的预处理倍数,也是
n
n
n\sqrt n
nn。查询时也是分块查询,对
n
n
n 分块,支持区间查询。
#include<bits/stdc++.h>
#define N 100005
using namespace std;
inline char GET_CHAR ( void )
{
static char buf[1<<23],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2) ? EOF : *p1++;
}
inline int read ( void )
{
int x=0;char ch;
while ( !isdigit(ch=GET_CHAR()) ) ;
for ( x=ch^48;isdigit(ch=GET_CHAR()); ) x=(x<<1)+(x<<3)+(ch^48);
return x;
}/*
int read(){
int op=1,sum=0;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}*/
int a[N],sq=320,cn[N][321],f[321][N];
int main(){
// freopen("papapa7.in","r",stdin);
// freopen("papapa.out","w",stdout);
int n=read(),q=read(),typ=read(),W=read();
//cout<<1<<endl;
for(int i=1;i<=n;++i){
a[i]=read();
//for(int j=1;j<=sq;++j)cn[i][j]+=cn[i-1][j];
/*if(a[i]<=sq){
++cn[i][a[i]];
continue;
}*/
for(int j=a[i];j<=W;j+=a[i])++f[(i-1)/sq+1][j];
}
for(int i=1;i<=(n-1)/sq+1;++i){
for(int j=1;j<=W;++j)f[i][j]+=f[i][j-1];
for(int j=1;j<=W;++j)f[i][j]+=f[i-1][j];
}
int ans=0;
//cout<<1<<endl;
while(q--){
int l=read(),r=read(),w=read();
if(typ){
l=(l^ans)%n+1;r=(r^ans)%n+1;w=(w^ans)%W+1;
if(l>r)swap(l,r);
}
ans=0;
//for(int i=1;i<=sq;++i)ans=ans+(w/i)*(cn[r][i]-cn[l-1][i]);
//cout<<ans<<endl;
int bl=(l-1)/sq+1,br=(r-1)/sq+1;
if(bl<=br-1)ans+=f[br-1][w]-f[bl][w];
for(int i=l;i<=min(bl*sq,r);++i)ans+=w/a[i];
if(bl!=br)for(int i=max(l,(br-1)*sq+1);i<=r;++i)ans+=w/a[i];
//ans>>=1;
printf("%d\n",ans);
}
return 0;
}