Description
六一儿童节到了, SHUXK 被迫陪着M个熊孩子玩一个无聊的游戏:
有
N
N
N个盒子从左到右排成一排,第
i
i
i个盒子里装着
A
i
A_i
Ai个气球。
SHUXK 要进行
Q
Q
Q次操作,每次从某一个盒子里拿出一个没被踩爆的气球,然后熊孩子们就会立刻把它踩爆。
这
M
M
M个熊孩子每个人都指定了一个盒子区间
[
L
i
,
R
i
]
[L_i, R_i]
[Li,Ri]。 如果某一个时刻,一个熊孩子发现自己选定的盒子区间
[
L
i
,
R
i
]
[L_i, R_i]
[Li,Ri]中的所有气球都已经被踩爆了,他就会非常高兴(显然之后他一直会很高兴)。
为了不辜负将自己的任务强行塞给 SHUXK 的那个人的期望, SHUXK 想向你询问:
他每次操作过后会有多少个熊孩子很高兴。
Input
第一行包含两个正整数
N
N
N和
M
M
M,分别表示盒子和熊孩子的个数。
第二行包含
N
N
N个正整数
A
i
(
1
<
=
A
i
<
=
1
0
5
)
A_i( 1 < = A_i < = 10^5)
Ai(1<=Ai<=105),表示每个盒子里气球的数量。
以下M行每行包含两个正整数
L
i
,
R
i
(
1
<
=
L
i
<
=
R
i
<
=
N
)
L_i, R_i( 1 < = L_i < = R_i < = N)
Li,Ri(1<=Li<=Ri<=N),分别表示每一个熊孩子指定的区间。
以下一行包含一个正整数
Q
Q
Q,表示 SHUXK 操作的次数。
以下
Q
Q
Q行每行包含一个正整数
X
X
X,表示这次操作是从第
X
X
X个盒子里拿气球。为
了体现在线,我们对输入的
X
X
X进行了加密。
假设输入的正整数是
x
′
x'
x′,那么真正的
X
=
(
x
′
+
L
a
s
t
a
n
s
−
1
)
m
o
d
  
N
+
1
X = (x' + Lastans − 1)\mod N + 1
X=(x′+Lastans−1)modN+1。其
中Lastans为上一次询问的答案。对于第一个询问,
L
a
s
t
a
n
s
=
0
Lastans = 0
Lastans=0。
输入数据保证
1
<
=
x
′
<
=
1
0
9
1 < = x' < = 10^9
1<=x′<=109, 且第X个盒子中有尚未被踩爆的气球。
N
<
=
1
0
5
,
M
<
=
1
0
5
,
Q
<
=
1
0
5
N < = 10^5 ,M < = 10^5 ,Q < = 10^5
N<=105,M<=105,Q<=105
Output
包含
Q
Q
Q行,每行输出一个整数,表示 SHUXK 一次操作后询问的
答案。答案的顺序应与输入数据的顺序保持一致。
Sample Input
5 3
1 1 1 1 1
5 5
2 2
1 3
5
4
2
5
2
3
Sample Output
0
1
1
2
3
【样例说明】
实际上每次操作的盒子是: 4 2 1 3 5
在第二次操作后,第二个熊孩子会高兴 (区间[2,2]中的气球已经全部被踩爆)。
在第四次操作后,第三个熊孩子会高兴(区间[1,3]中的气球已经全部被踩爆)。
在第五次操作后,第一个熊孩子会高兴(区间[5,5]中的气球已经全部被踩爆)。
分析:
可以暴力修改,只有当某一位减至
0
0
0 时,答案才有可能出现变化。
考虑新增的区间数,显然只有当这个区间只有这一位不是
0
0
0时才有贡献。
对于每一个位置
x
x
x,考虑他左边和右边的全
0
0
0区间长度,记为
L
L
L和
R
R
R。这个可以使用并查集进行维护,可以通过维护集合大小来算出。
新增的答案就是左边界在
[
x
−
L
,
x
]
[x-L,x]
[x−L,x],右边界在
[
x
,
x
+
R
]
[x,x+R]
[x,x+R]的区间个数。可以给区间按左边界排序,使用主席树。每个右边界权值位置+1,然后求和即可。
复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的。
代码:
/**************************************************************
Problem: 4631
User: ypxrain
Language: C++
Result: Accepted
Time:1416 ms
Memory:27464 kb
****************************************************************/
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
const int maxn=1e5+7;
using namespace std;
int n,m,T,x,ans,cnt;
int a[maxn],root[maxn],num[maxn],p[maxn],val[maxn];
struct rec{
int l,r;
}e[maxn];
struct node{
int l,r,data;
}t[maxn*20];
void ins(int &p,int q,int l,int r,int x,int k)
{
if (!p) p=++cnt;
t[p].data=t[q].data+1;
if (l==r) return;
int mid=(l+r)/2;
if (x<=mid) t[p].r=t[q].r,ins(t[p].l,t[q].l,l,mid,x,k);
else t[p].l=t[q].l,ins(t[p].r,t[q].r,mid+1,r,x,k);
}
int getsum(int p,int q,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p].data-t[q].data;
int mid=(l+r)/2;
if (y<=mid) return getsum(t[p].l,t[q].l,l,mid,x,y);
else if (x>mid) return getsum(t[p].r,t[q].r,mid+1,r,x,y);
else return getsum(t[p].l,t[q].l,l,mid,x,mid)+getsum(t[p].r,t[q].r,mid+1,r,mid+1,y);
}
int find(int x)
{
if (!p[x]) return x;
return p[x]=find(p[x]);
}
void uni(int x,int y)
{
int u=find(x),v=find(y);
if (u==v) return;
p[u]=v;
val[v]+=val[u];
}
bool cmp(rec a,rec b)
{
return a.l<b.l;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=m;i++) scanf("%d%d",&e[i].l,&e[i].r);
sort(e+1,e+m+1,cmp);
int k=1;
for (int i=1;i<=n;i++)
{
while (e[k].l==i)
{
ins(root[k],root[k-1],1,n,e[k].r,1);
k++;
}
num[i]=k-1;
}
scanf("%d",&T);
int l,r;
for (int i=1;i<=T;i++)
{
scanf("%d",&x);
x=(x+ans-1)%n+1;
a[x]--;
if (!a[x])
{
val[x]++;
l=val[find(x-1)],r=val[find(x+1)];
if ((x>1) && (!a[x-1])) uni(x-1,x);
if ((x<n) && (!a[x+1])) uni(x,x+1);
ans+=getsum(root[num[x]],root[num[x-l-1]],1,n,x,x+r);
}
printf("%d\n",ans);
}
}