1
≤
n
≤
65000
1\le n\le 65000
1≤n≤65000 且
s
s
s 不包含
0
0
0
题解
∑
i
=
1
n
i
[
s
[
i
]
是
偶
数
]
\sum_{i=1}^ni[s[i]是偶数]
i=1∑ni[s[i]是偶数]
代码
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}typedeflonglong ll;constint N =1e5+5;int n;char s[N];
ll ans;intmain(){
n =read();scanf("%s", s +1);for(int i =1; i <= n; i++)if(s[i]-'0'+1&1) ans += i;
std::cout << ans << std::endl;return0;}
B
题意
一个长度为
n
n
n 的正整数数组
a
a
a
求一个长度为
n
n
n 的非负数组
x
x
x ,满足
(1)对于所有的
1
≤
i
≤
n
1\le i\le n
1≤i≤n ,有
0
≤
x
i
≤
a
i
0\le x_i\le a_i
0≤xi≤ai
(2)对于所有的
1
≤
j
<
i
≤
n
1\le j<i\le n
1≤j<i≤n ,有
x
j
=
0
x_j=0
xj=0 或
x
j
<
x
i
x_j<x_i
xj<xi
(3)最大化
∑
i
=
1
n
x
i
\sum_{i=1}^nx_i
∑i=1nxi
求这个最大值
1
≤
n
≤
2
×
1
0
5
1\le n\le 2\times10^5
1≤n≤2×105 ,
1
≤
a
i
≤
1
0
9
1\le a_i\le 10^9
1≤ai≤109
题解
从右到左考虑,显然每个
x
i
x_i
xi 需要取到它能取到的最大值
也就是说
(1)
x
n
=
a
n
x_n=a_n
xn=an
(2)
x
i
=
min
(
a
i
,
max
(
0
,
x
i
+
1
−
1
)
)
x_i=\min(a_i,\max(0,x_{i+1}-1))
xi=min(ai,max(0,xi+1−1)) ,
1
≤
i
<
n
1\le i<n
1≤i<n
代码
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Min(const T &a,const T &b){return a < b ? a : b;}typedeflonglong ll;constint N =2e5+5;int n, a[N], wt;
ll ans;intmain(){
n =read();for(int i =1; i <= n; i++) a[i]=read(); wt = a[n]+1;for(int i = n; i >=1; i--){
wt--;if(wt <0) wt =0;
wt =Min(wt, a[i]);
ans += wt;}
std::cout << ans << std::endl;return0;}
C
题意
一棵
n
n
n 个节点的树,边有红边和黑边
求有多少个节点序列
a
1
…
k
a_{1\dots k}
a1…k
满足
a
1
a_1
a1 到
a
2
a_2
a2 ,
a
2
a_2
a2 到
a
3
a_3
a3 ,
…
\dots
… ,
a
k
−
1
a_{k-1}
ak−1 到
a
k
a_k
ak 这
k
−
1
k-1
k−1 条路径中存在一条经过了至少一条黑边
2
≤
n
≤
1
0
5
2\le n\le10^5
2≤n≤105 ,
2
≤
k
≤
100
2\le k\le100
2≤k≤100
题解
容易想到一个经典的 O(nk) 树形 DP
用总方案数
n
k
n^k
nk 减掉不经过黑边的方案数
显然,如果只加入所有红边,那么不经过黑边的方案数,就是节点序列
a
1
…
k
a_{1\dots k}
a1…k 中所有点位于同一个连通块内的方案数
用并查集维护连通块大小
答案就是
n
k
n^k
nk 减去所有连通块的大小的
k
k
k 次幂之和
代码
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =1e5+5, ZZQ =1e9+7;intqpow(int a,int b){int res =1;while(b){if(b &1) res =1ll* res * a % ZZQ;
a =1ll* a * a % ZZQ;
b >>=1;}return res;}int n, k, fa[N], sze[N], ans;intcx(int x){if(fa[x]!= x) fa[x]=cx(fa[x]);return fa[x];}voidzm(int x,int y){int ix =cx(x), iy =cx(y);if(ix != iy) fa[iy]= ix, sze[ix]+= sze[iy];}intmain(){int x, y, z;
n =read(); k =read();for(int i =1; i <= n; i++) fa[i]= i, sze[i]=1;for(int i =1; i < n; i++){
x =read(); y =read(); z =read();if(!z)zm(x, y);}for(int i =1; i <= n; i++)if(fa[i]== i) ans =(qpow(sze[i], k)+ ans)% ZZQ;
std::cout <<(qpow(n, k)- ans + ZZQ)% ZZQ << std::endl;return0;}
D
题意
给定正整数
m
m
m ,你有一个空集合
a
a
a
每次你可以等概率随机一个
[
1
,
m
]
[1,m]
[1,m] 内的正整数加入集合
a
a
a
加入之后,如果集合
a
a
a 内所有数的
gcd
\gcd
gcd 为
1
1
1 则结束过程,否则继续随机
求过程结束后集合
a
a
a 的期望大小
1
≤
m
≤
100000
1\le m\le 100000
1≤m≤100000
算法:莫比乌斯反演 + 期望 DP
状态
f
[
i
]
f[i]
f[i] 表示当前集合
a
a
a 的
gcd
\gcd
gcd 为
i
i
i 的情况下,期望加入多少个数之后这个
gcd
\gcd
gcd 变成
1
1
1
显然有
f
[
1
]
=
0
f[1]=0
f[1]=0
f
[
i
]
=
1
+
1
m
∑
j
=
1
m
f
[
gcd
(
i
,
j
)
]
f[i]=1+\frac 1m\sum_{j=1}^mf[\gcd(i,j)]
f[i]=1+m1j=1∑mf[gcd(i,j)]
发现
gcd
(
i
,
j
)
\gcd(i,j)
gcd(i,j) 的取值个数只有
i
i
i 的约数个数,所以把枚举
j
j
j 改成枚举
gcd
(
i
,
j
)
\gcd(i,j)
gcd(i,j)
f
[
i
]
+
1
+
1
m
∑
d
∣
i
f
[
d
]
×
c
n
t
(
d
,
i
)
f[i]+1+\frac 1m\sum_{d|i}f[d]\times cnt(d,i)
f[i]+1+m1d∣i∑f[d]×cnt(d,i)
c
n
t
(
d
,
i
)
cnt(d,i)
cnt(d,i) 表示
[
1
,
m
]
[1,m]
[1,m] 内有多少个数与
i
i
i 的
gcd
\gcd
gcd 等于
d
d
d
另设
g
(
i
,
j
)
g(i,j)
g(i,j) 表示
[
1
,
i
]
[1,i]
[1,i] 内有多少个数与
j
j
j 互质
显然有
c
n
t
(
d
,
i
)
=
g
(
⌊
m
d
⌋
,
i
d
)
cnt(d,i)=g(\lfloor\frac md\rfloor,\frac id)
cnt(d,i)=g(⌊dm⌋,di)
注意到
∑
i
=
1
m
m
i
=
O
(
m
log
m
)
\sum_{i=1}^m\frac mi=O(m\log m)
∑i=1mim=O(mlogm)
所以考虑求出所有的
i
j
≤
m
ij\le m
ij≤m ,对应
g
(
⌊
m
i
⌋
,
j
)
g(\lfloor\frac mi\rfloor,j)
g(⌊im⌋,j) 的值
那么对于给定的
a
≥
b
a\ge b
a≥b ,如何求有多少个
1
≤
i
≤
a
1\le i\le a
1≤i≤a 满足
gcd
(
i
,
b
)
=
1
\gcd(i,b)=1
gcd(i,b)=1 呢?
如果不是满足
gcd
(
i
,
b
)
=
1
\gcd(i,b)=1
gcd(i,b)=1 而是满足
x
∣
gcd
(
i
,
b
)
x|\gcd(i,b)
x∣gcd(i,b) ,则这显然为
⌊
a
x
⌋
\lfloor\frac ax\rfloor
⌊xa⌋
所以,考虑反演,得
g
(
a
,
b
)
=
∑
x
∣
b
μ
(
x
)
⌊
a
x
⌋
g(a,b)=\sum_{x|b}\mu(x)\lfloor\frac ax\rfloor
g(a,b)=x∣b∑μ(x)⌊xa⌋
线性筛
μ
\mu
μ 之后就可以在
O
(
b
的
约
数
个
数
)
O(b的约数个数)
O(b的约数个数) 的时间内求出
设
D
(
x
)
D(x)
D(x) 为
x
x
x 的约数个数,那么对每对
i
j
≤
m
ij\le m
ij≤m 进行计算的总复杂度为
∑
i
=
1
m
∑
j
=
1
⌊
m
i
⌋
D
(
j
)
=
∑
i
=
1
m
∑
j
=
1
⌊
m
i
⌋
⌊
⌊
m
i
⌋
j
⌋
=
∑
i
=
1
m
⌊
m
i
⌋
log
m
=
O
(
m
log
2
m
)
\sum_{i=1}^m\sum_{j=1}^{\lfloor\frac mi\rfloor}D(j)=\sum_{i=1}^m\sum_{j=1}^{\lfloor\frac mi\rfloor}\lfloor\frac{\lfloor\frac mi\rfloor}j\rfloor=\sum_{i=1}^m\lfloor\frac mi\rfloor\log m=O(m\log^2m)
i=1∑mj=1∑⌊im⌋D(j)=i=1∑mj=1∑⌊im⌋⌊j⌊im⌋⌋=i=1∑m⌊im⌋logm=O(mlog2m)
回到这个转移
f
[
i
]
+
1
+
1
m
∑
d
∣
i
f
[
d
]
×
c
n
t
(
d
,
i
)
f[i]+1+\frac 1m\sum_{d|i}f[d]\times cnt(d,i)
f[i]+1+m1d∣i∑f[d]×cnt(d,i)
发现
d
d
d 可以等于
i
i
i ,得不到转移的目的,所以做一些移项
(
1
−
c
n
t
(
i
,
i
)
m
)
f
[
i
]
=
1
+
1
m
∑
d
∣
i
,
d
≠
i
f
[
d
]
×
c
n
t
(
d
,
i
)
(1-\frac{cnt(i,i)}m)f[i]=1+\frac1m\sum_{d|i,d\ne i}f[d]\times cnt(d,i)
(1−mcnt(i,i))f[i]=1+m1d∣i,d̸=i∑f[d]×cnt(d,i)
f
[
i
]
=
1
1
−
c
n
t
(
i
,
i
)
m
(
1
+
1
m
∑
d
∣
i
,
d
≠
i
f
[
d
]
×
c
n
t
(
d
,
i
)
)
f[i]=\frac1{1-\frac{cnt(i,i)}m}(1+\frac1m\sum_{d|i,d\ne i}f[d]\times cnt(d,i))
f[i]=1−mcnt(i,i)1(1+m1d∣i,d̸=i∑f[d]×cnt(d,i))
于是我们就可以转移了
考虑如何算答案
由于第一个数可以随便取,所以答案为
1
m
∑
i
=
1
m
(
1
+
f
[
i
]
)
\frac1m\sum_{i=1}^m(1+f[i])
m1i=1∑m(1+f[i])
看到某人的提交记录里有吊打标算的非 DP 做法,复杂度仿佛是
O
(
m
log
m
)
O(m\log m)
O(mlogm) ,所以有更优做法欢迎提出
代码
该代码中的
f
[
i
]
f[i]
f[i] 表示的是题解中的
f
[
i
]
f[i]
f[i] 加一,答案为
1
m
∑
i
=
1
m
f
[
i
]
\frac1m\sum_{i=1}^mf[i]
m1∑i=1mf[i] ,边界为
f
[
1
]
=
1
f[1]=1
f[1]=1 ,见谅
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =1e5+5, ZZQ =1e9+7;intqpow(int a,int b){int res =1;while(b){if(b &1) res =1ll* res * a % ZZQ;
a =1ll* a * a % ZZQ;
b >>=1;}return res;}int n, f[N], miu[N], tot, pri[N], inv[N], wt[N], num[N], res[N], ans;bool mark[N];
std::vector<int> divi[N], cont[N];intsolve(int n,int m){int tt = divi[m].size(), res =0;for(int i =0; i < tt; i++){int x = divi[m][i];
res += miu[x]*(n / x);}return res;}voidsieve(){
mark[0]= mark[miu[1]=1]=1;for(int i =2; i <= n; i++){if(!mark[i]) miu[pri[++tot]= i]=-1;for(int j =1; j <= tot; j++){if(1ll* i * pri[j]> n)break;
mark[i * pri[j]]=1;if(i % pri[j]==0)break;else miu[i * pri[j]]=-miu[i];}}for(int i =1; i <= n; i++)for(int j = i; j <= n; j += i)
divi[j].push_back(i);for(int i =1; i <= n;){int nxt = n /(n / i);for(int j =1; j <= n / i; j++) res[j]=solve(n / i, j);for(int j = i; j <= nxt; j++)for(int k = j; k <= n; k += j)
cont[k].push_back(res[k / j]);
i = nxt +1;}}intmain(){
n =read();
inv[1]=1;for(int i =2; i <= n; i++)
inv[i]=1ll*(ZZQ - ZZQ / i)* inv[ZZQ % i]% ZZQ;sieve();
f[1]=1;for(int i =2; i <= n; i++){int tt = divi[i].size();for(int j =0; j < tt; j++)
wt[j +1]=1ll* inv[n]* cont[i][j]% ZZQ, num[j +1]= divi[i][j];int qt =qpow((1- wt[tt]+ ZZQ)% ZZQ, ZZQ -2);for(int j =1; j < tt; j++) wt[j]=1ll* wt[j]* qt % ZZQ;
f[i]= qt;for(int j =1; j < tt; j++)
f[i]=(1ll* wt[j]* f[num[j]]+ f[i])% ZZQ;}for(int i =1; i <= n; i++)
ans =(1ll* inv[n]* f[i]+ ans)% ZZQ;
std::cout << ans << std::endl;return0;}
E
题意
有
m
m
m 个集合和
n
n
n 个元素,每个元素一开始属于恰好一个集合,且第
i
i
i 个元素的属性值为
p
i
p_i
pi
1
≤
m
≤
n
≤
5000
1\le m\le n\le5000
1≤m≤n≤5000 ,
0
≤
p
i
≤
5000
0\le p_i\le5000
0≤pi≤5000
算法:二分图匹配
建一张二分图,一侧是属性值,一侧是集合,对于每个元素
i
i
i 由
p
i
p_i
pi 向其所属集合连一条边
这样,如果
x
x
x 为满足属性值
[
0
,
x
]
[0,x]
[0,x] 都能找到匹配的最大
x
x
x ,答案就是
x
+
1
x+1
x+1
发现二分图删边不好处理,所以考虑倒着加边,在加边的过程中维护最大匹配
维护当前的最大
x
x
x
当加一条边之后,需要更新匹配数
具体地,尝试对点
x
+
1
x+1
x+1 寻找匹配
如果找得到匹配则将
x
x
x 加一,否则停止当前的匹配
由于属性值一侧的每个点最多寻找一次匹配,所以复杂度
O
(
n
max
p
)
O(n\max p)
O(nmaxp)
代码
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Max(const T &a,const T &b){return a > b ? a : b;}constint N =3e4+5;int n, m, tot, p[N], c[N], d, k[N], ecnt, nxt[N], adj[N], go[N], ans[N],
QAQ, vis[N], my[N], now;bool del[N];voidadd_edge(int u,int v){
nxt[++ecnt]= adj[u]; adj[u]= ecnt; go[ecnt]= v;}booldfs(int u){for(int e = adj[u], v = go[e]; e; e = nxt[e], v = go[e])if(vis[v]< QAQ){
vis[v]= QAQ;if(my[v]==-1||dfs(my[v]))return my[v]= u,1;}return0;}boolfind_match(int x){
QAQ++;returndfs(x);}intmain(){memset(my,-1,sizeof(my));
n =read(); m =read();for(int i =1; i <= n; i++) tot =Max(tot, p[i]=read());for(int i =1; i <= n; i++) c[i]=read();
d =read();for(int i =1; i <= d; i++) del[k[i]=read()]=1;for(int i =1; i <= n; i++)if(!del[i])add_edge(p[i], tot + c[i]);for(int i = d; i >=1; i--){while(now <= tot &&find_match(now)) now++;
ans[i]= now;add_edge(p[k[i]], tot + c[k[i]]);}for(int i =1; i <= d; i++)printf("%d\n", ans[i]);return0;}
F
题意
n
n
n 种菜和
m
m
m 个人
每种菜
i
i
i 有三个属性
p
i
,
s
i
,
b
i
p_i,s_i,b_i
pi,si,bi
每个人
j
j
j 有两个属性
i
n
c
j
,
p
r
e
f
j
inc_j,pref_j
incj,prefj
一个人
j
j
j 能品尝菜
i
i
i 当且仅当
p
i
≤
i
n
c
j
≤
s
i
p_i\le inc_j\le s_i
pi≤incj≤si 且
∣
b
i
−
p
r
e
f
j
∣
≤
i
n
c
j
−
p
i
|b_i-pref_j|\le inc_j-p_i
∣bi−prefj∣≤incj−pi
求每个人能品尝多少种菜
1
≤
n
,
m
≤
1
0
5
1\le n,m\le 10^5
1≤n,m≤105 ,其他数据均为
1
0
9
10^9
109 级别
算法:扫描线 + 树状数组
此题有一个非常套路的
O
(
(
n
+
m
)
log
2
n
)
O((n+m)\log^2n)
O((n+m)log2n) 做法( CDQ 分治)和一个比较妙的官方题解做法,复杂度少一个
log
\log
log ,下面只讨论后者
首先,
∣
b
i
−
p
r
e
f
j
∣
≤
i
n
c
j
−
p
i
|b_i-pref_j|\le inc_j-p_i
∣bi−prefj∣≤incj−pi 就相当于
b
i
−
p
r
e
f
j
≤
i
n
c
j
−
p
i
b_i-pref_j\le inc_j-p_i
bi−prefj≤incj−pi 且
p
r
e
f
j
−
b
i
≤
i
n
c
j
−
p
i
pref_j-b_i\le inc_j-p_i
prefj−bi≤incj−pi
把问题抽象到二维平面上,一个点
(
x
,
y
)
(x,y)
(x,y) 表示一个人的
i
n
c
inc
inc 为
x
x
x ,
p
r
e
f
pref
pref 为
y
y
y
整理一下得出条件
(1)
p
i
≤
i
n
c
j
≤
s
i
p_i\le inc_j\le s_i
pi≤incj≤si
(2)
i
n
c
j
+
p
r
e
f
j
≥
b
i
+
p
i
inc_j+pref_j\ge b_i+p_i
incj+prefj≥bi+pi
(3)
p
r
e
f
j
−
i
n
c
j
≤
b
i
−
p
i
pref_j-inc_j\le b_i-p_i
prefj−incj≤bi−pi
这相当于点
(
i
n
c
j
,
p
r
e
f
j
)
(inc_j,pref_j)
(incj,prefj) 位于如下图所示的三角形内(含边界)
考虑扫描线,把所有人离线按照
i
n
c
inc
inc 排序,按照
x
x
x 坐标递增的顺序扫描,当扫到
b
i
b_i
bi 时加入第
i
i
i 个三角形的影响,扫到
s
i
+
1
s_i+1
si+1 时去除第
i
i
i 个三角形的影响
我们对于每个人
(
i
n
c
j
,
p
r
e
f
j
)
(inc_j,pref_j)
(incj,prefj) 需要询问这个点在多少个三角形内
考虑差分,也就是说当
x
=
x
0
x=x_0
x=x0 时,如果直线
x
=
x
0
x=x_0
x=x0 经过了第
i
i
i 个三角形且
y
y
y 坐标范围
[
l
,
r
]
[l,r]
[l,r] 被第
i
i
i 个三角形覆盖,则在
l
l
l 处贡献
1
1
1 ,
r
+
1
r+1
r+1 处贡献
−
1
-1
−1 ,则当
i
n
c
j
=
x
0
inc_j=x_0
incj=x0 时,单点询问
(
i
n
c
j
,
p
r
e
f
j
)
(inc_j,pref_j)
(incj,prefj) 转化成询问前缀和
p
r
e
f
j
pref_j
prefj
于是我们考虑第
i
i
i 个三角形的影响,可以看成
(1)在直线
x
+
y
=
b
i
+
p
i
x+y=b_i+p_i
x+y=bi+pi 上贡献
1
1
1
(2)在直线
y
−
x
=
b
i
−
p
i
+
1
y-x=b_i-p_i+1
y−x=bi−pi+1 上贡献
−
1
-1
−1
消除第
i
i
i 个三角形的影响则同理
询问相当于询问横坐标为
i
n
c
j
inc_j
incj ,纵坐标不超过
p
r
e
f
j
pref_j
prefj 的贡献之和
用两个数据结构
A
A
A 和
B
B
B 分别记录
x
+
y
x+y
x+y 和
y
−
x
y-x
y−x 的贡献
直线
x
+
y
=
k
x+y=k
x+y=k 能为
(
i
n
c
j
,
p
r
e
f
j
)
(inc_j,pref_j)
(incj,prefj) 贡献当且仅当
k
≤
i
n
c
j
+
p
r
e
f
j
k\le inc_j+pref_j
k≤incj+prefj
所以加入第
i
i
i 个三角形时,在数据结构
A
A
A 的
b
i
+
p
i
b_i+p_i
bi+pi 处进行单点加
1
1
1
直线
y
−
x
=
k
y-x=k
y−x=k 能为询问贡献当且仅当
k
≤
p
r
e
f
j
−
i
n
c
j
k\le pref_j-inc_j
k≤prefj−incj
所以加入第
i
i
i 个三角形时,在数据结构
B
B
B 的
b
i
−
p
i
+
1
b_i-p_i+1
bi−pi+1 处进行单点加
1
1
1
这样第
j
j
j 个询问的答案就是当
x
x
x 扫描到
i
n
c
j
inc_j
incj 时,数据结构
A
A
A 的前缀和
i
n
c
j
+
p
r
e
f
j
inc_j+pref_j
incj+prefj 减去数据结构
B
B
B 的前缀和
p
r
e
f
j
−
i
n
c
j
pref_j-inc_j
prefj−incj
可以用树状数组等实现
复杂度
O
(
(
n
+
m
)
log
(
n
+
m
)
)
O((n+m)\log(n+m))
O((n+m)log(n+m))
代码
#include<bits/stdc++.h>// 20030830inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =1e5+5, M = N <<2;int n, m, p[N], s[N], b[N], inc[N], pref[N], tot, a[M], A[M], B[M], cnt, ans[N];struct node
{int tm, x, y, op, id;} que[M];inlineboolcomp(node a, node b){return a.tm < b.tm ||(a.tm == b.tm && a.op < b.op);}voidchangeA(int x,int v){for(; x <= tot; x += x &-x)
A[x]+= v;}intaskA(int x){int res =0;for(; x; x -= x &-x)
res += A[x];return res;}voidchangeB(int x,int v){for(; x <= tot; x += x &-x)
B[x]+= v;}intaskB(int x){int res =0;for(; x; x -= x &-x)
res += B[x];return res;}intmain(){
n =read(); m =read();for(int i =1; i <= n; i++) p[i]=read();for(int i =1; i <= n; i++) s[i]=read();for(int i =1; i <= n; i++) b[i]=read();for(int i =1; i <= m; i++) inc[i]=read();for(int i =1; i <= m; i++) pref[i]=read();for(int i =1; i <= n; i++)
a[++tot]= p[i]+ b[i], a[++tot]= b[i]- p[i]+1;for(int i =1; i <= m; i++)
a[++tot]= inc[i]+ pref[i], a[++tot]= pref[i]- inc[i];
std::sort(a +1, a + tot +1);int tt = std::unique(a +1, a + tot +1)- a -1;
tot = tt;for(int i =1; i <= n; i++)
que[++cnt]=(node){p[i], p[i], b[i],1,0},
que[++cnt]=(node){s[i]+1, p[i], b[i],-1,0};for(int i =1; i <= m; i++)
que[++cnt]=(node){inc[i], inc[i], pref[i],2, i};
std::sort(que +1, que + cnt +1, comp);for(int i =1; i <= cnt; i++)if(que[i].op <=1){changeA(std::lower_bound(a +1, a + tot +1,
que[i].x + que[i].y)- a, que[i].op);changeB(std::lower_bound(a +1, a + tot +1,
que[i].y - que[i].x +1)- a, que[i].op);}else ans[que[i].id]=askA(std::lower_bound(a +1, a + tot +1,
que[i].x + que[i].y)- a)-askB(std::lower_bound(a +1, a + tot +1,
que[i].y - que[i].x)- a);for(int i =1; i <= m; i++)printf("%d ", ans[i]);returnputs(""),0;}