文章目录
前言
789 AB比较水,但是B分情况讨论也可以锻炼严谨思维
788ABC都是码量小也不太难的小清新题,C比较令人耳目一新
788D的思路让人难以想到
788E标准的大数据结构题
CF789A Anastasia and pebbles
Description \text{Description} Description
Anastasia喜欢去公园收集石子.她有 2 2 2 个口袋,每个口袋最多装 k k k 个石子.
但她每天只去公园 1 1 1 次,而且每次同一个口袋里只装同一种石子.问要装完 n n n 种石子共要花多少天?
输入 n n n,以及每一种石子的数量 w i w_i wi. 输出上述所求答案.
1 ≤ n ≤ 100000 ; 1 ≤ k ≤ 1000000000 ; 1 ≤ w i ≤ 10000 1\le n\le 100000;1\le k\le 1000000000; 1\le w_i\le10000 1≤n≤100000;1≤k≤1000000000;1≤wi≤10000
Solution \text{Solution} Solution
求出每种石子需要几袋子装,全部加起来除以二上取整即可.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
ll n,m,k;
ll x[N],a[N],sum[N];
ll mn,mx,ans;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=1;i<=n;i++) x[i]=read();
for(int i=1;i<n;i++) a[i]=abs(x[i]-x[i+1])*((i&1)?1:-1);
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+a[i];
if(i&1) ans=max(ans,sum[i]-mn);
else ans=max(ans,mx-sum[i]);
mx=max(mx,sum[i]);mn=min(mn,sum[i]);
}
printf("%lld\n",ans);
return 0;
}
/*
*/
CF789B Masha and geometric depression
Description \text{Description} Description
给你一个等比数列,首项为
b
1
b_1
b1,公比为
q
q
q.
现在Masha在黑板上从首项开始书写这个等比数列,直到数列某项的绝对值大于
l
l
l,给定
m
m
m 个整数,若该等比数列中的某项等同于这
m
m
m 个整数,则不会被写出.
问Masha会写出多少个数字?如果她会写出无穷多个数字,输出inf
.
注意:
b
1
,
q
b1,q
b1,q 可能为
0
0
0.
Solution \text{Solution} Solution
大特判题.
特判一下公差等于
0
/
1
/
−
1
0/1/-1
0/1/−1,首项等于
0
0
0 的情况,其他的暴力算即可.
需要开 longlong.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,mx;
ll d,x;
map<ll,bool>mp;
int ans;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
x=read();d=read();mx=read();n=read();
for(int i=1;i<=n;i++) mp[read()]=1;
if(abs(x)>mx){
printf("0");return 0;
}
if(d==0){
if(mp[0]) printf("%d",!mp[x]);
else printf("inf");
}
else if(d==1){
if(mp[x]) printf("0");
else printf("inf");
}
else if(d==-1){
if(mp[x]&&mp[-x]) printf("0");
else printf("inf");
}
else if(x==0){
if(mp[0]) printf("0");
else printf("inf");
}
else{
while(abs(x)<=mx){
if(!mp[x]) ++ans;
x*=d;
}
printf("%d\n",ans);
}
return 0;
}
/*
*/
CF788A Functions again
Description \text{Description} Description
定义一个函数,函数如下:
f
[
l
,
r
]
=
∑
i
=
l
r
−
1
∣
a
i
−
a
i
+
1
∣
×
(
−
1
)
i
−
l
f[l,r]=\sum^{r-1}_{i=l}|a_i-a_{i+1}|\times (-1)^{i-l}
f[l,r]=∑i=lr−1∣ai−ai+1∣×(−1)i−l. (
1
≤
l
,
r
≤
n
1\le l,r\le n
1≤l,r≤n)
∣
x
∣
|x|
∣x∣ 表示
x
x
x 的绝对值.
现在给你一个函数,请取恰当的
l
,
r
l,r
l,r 使
f
f
f 值最大,请输出最大的
f
f
f 值.
2
≤
n
≤
1
0
5
2\le n\le 10^5
2≤n≤105
Solution \text{Solution} Solution
先求出差分数组的绝对值
d
1...
n
−
1
d_{1...n-1}
d1...n−1.
定义:
s
u
m
i
=
∑
j
=
1
i
d
j
×
(
−
1
)
j
+
1
sum_i=\sum_{j=1}^i d_j\times(-1)^{j+1}
sumi=j=1∑idj×(−1)j+1
那么我们的
f
l
,
r
f_{l,r}
fl,r 就可以表示为:
(
−
1
)
r
+
1
×
(
s
u
m
r
−
s
u
m
l
−
1
)
(-1)^{r+1}\times (sum_r-sum_{l-1})
(−1)r+1×(sumr−suml−1)
所以从前往后扫分别记录
s
u
m
sum
sum 的最大值和最小值即可.
Description \text{Description} Description
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
ll n,m,k;
ll x[N],a[N],sum[N];
ll mn,mx,ans;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=1;i<=n;i++) x[i]=read();
for(int i=1;i<n;i++) a[i]=abs(x[i]-x[i+1])*((i&1)?1:-1);
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+a[i];
if(i&1) ans=max(ans,sum[i]-mn);
else ans=max(ans,mx-sum[i]);
mx=max(mx,sum[i]);mn=min(mn,sum[i]);
}
printf("%lld\n",ans);
return 0;
}
/*
*/
CF788B Weird journey
Description \text{Description} Description
总共有
n
n
n 个节点,
m
m
m 条路径,要求其中
m
−
2
m-2
m−2 条路径走两遍,剩下
2
2
2 条路径仅走一遍,问不同的路径总数有多少,如果仅走一遍的两条边不同则将这两条路径视为不同.
n
,
m
≤
1
0
6
n,m\le10^6
n,m≤106
Solution \text{Solution} Solution
把每条边拆成两个一样的边,考虑欧拉回路的条件.
由于拆了边,显然每个点的度数都是偶数.
所以选择的两条边必须含有公共端点.
考虑自环如何处理.
删掉自环后该点的度数还是偶数,所以剩下的一条边随便删即可.
细节上,需要判断含有边的点必须连通.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e6+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
int du[N];
int fa[N],tag[N];
ll num;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int x=read(),y=read();
fa[find(x)]=find(y);
tag[x]=tag[y]=1;
if(x==y){
++num;continue;
}
++du[x];++du[y];
}
int cnt(0);
for(int i=1;i<=n;i++){
cnt+=(find(i)==i&&tag[i]!=0);
}
if(cnt>1||m<2){
printf("0");return 0;
}
ll ans(0);
for(int i=1;i<=n;i++){
ans+=1ll*du[i]*(du[i]-1)/2;
//printf("i=%d du=%d ans=%lld\n",i,du[i],ans);
}
ans+=num*(m-num)+num*(num-1)/2;
printf("%lld\n",ans);
return 0;
}
/*
*/
CF788C The Great Mixing
Description \text{Description} Description
有
k
k
k 种可乐,第
i
i
i 瓶可乐的 CO2 浓度是
a
i
1000
\frac{a_i}{1000}
1000ai,问要配置出浓度
n
1000
\frac{n}{1000}
1000n 的可乐,最少需要几瓶可乐.
无解输出
−
1
-1
−1.
0
≤
n
≤
1000
,
k
≤
1
0
6
0\le n\le 1000,k\le10^6
0≤n≤1000,k≤106
Solution \text{Solution} Solution
不难想到把所以值减
n
n
n 然后转化为加和为
0
0
0 的问题.
我的做法是正负两边暴力背包,值域在最差的情况下是
500
×
499
500\times499
500×499.
然后就
3
×
1
0
5
3\times 10^5
3×105艹过去了…
现在讲讲
n
2
n^2
n2 的正解.
考虑 bfs.
从
0
0
0 开始,向外寻找.
把边界设为
1000
1000
1000 即可.
为什么这么是对的?
设答案的组合为
x
1
+
x
2
+
.
.
.
x
k
=
0
x_1+x_2+...x_k=0
x1+x2+...xk=0.
不难发现,通过调整前后顺序,一定可以使序列
x
x
x 的任意一个前缀和的绝对值均不超过
1000
1000
1000,那么这个调整后的序列就可以被 bfs 搜到.
因此这样做是正确的.
Code \text{Code} Code
代码还是之前的暴力背包
bfs 不难实现,留给读者自行思考
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e6+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,k;
int a[1050],b[1050],x,y;
int o=3e5;
int w[N];
int f1[300050],f2[300050];
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();k=read();
for(int i=1;i<=k;i++) w[i]=read();
sort(w+1,w+1+k);
k=unique(w+1,w+1+k)-w-1;
for(int i=1;i<=k;i++){
w[i]-=n;
if(w[i]==0){
printf("1");return 0;
}
else if(w[i]>0) a[++x]=w[i];
else b[++y]=-w[i];
}
if(!x||!y){
printf("-1");return 0;
}
memset(f1,0x3f,sizeof(f1));
f1[0]=0;
for(int i=1;i<=x;i++){
int w=a[i];
for(int j=w;j<=o;j++) f1[j]=min(f1[j],f1[j-w]+1);
}
memset(f2,0x3f,sizeof(f2));
f2[0]=0;
for(int i=1;i<=y;i++){
int w=b[i];
for(int j=w;j<=o;j++) f2[j]=min(f2[j],f2[j-w]+1);
}
int ans=2e9;
for(int i=1;i<=o;i++) ans=min(ans,f1[i]+f2[i]);
printf("%d\n",ans);
return 0;
}
/*
*/
CF788D Finding lines
Description \text{Description} Description
有一个平面,上面有一些水平或竖直的直线.
你每次可以选择一个点,询问距离该点最近的直线到该点的距离.
请求出所有的直线的横/纵坐标.
总直线数不超过
1
0
4
10^4
104.
坐标范围不超过
1
0
8
10^8
108.(询问的点也不能超过该范围)
Solution \text{Solution} Solution
思路很妙的一道题.
不难想到利用 分治.
如何设计分治状态是本题的关键.
第一感似乎是设计
s
o
l
v
e
(
x
1
,
x
2
,
y
1
,
y
2
)
solve(x1,x2,y1,y2)
solve(x1,x2,y1,y2) 表示寻找横坐标在
(
x
1
,
x
2
)
(x1,x2)
(x1,x2) 和纵坐标在
(
y
1
,
y
2
)
(y1,y2)
(y1,y2) 的直线,然后找到这个矩形的中点尝试.
但是这样分治的两个子结构不互相独立,左边找到的直线也会影响右边,难以处理.
别问我为什么知道难以处理
所以我们要尝试一些特别的设计.
设计
s
o
l
v
e
(
l
,
r
)
solve(l,r)
solve(l,r) 表示解决坐标在
(
l
,
r
)
(l,r)
(l,r) 的直线(同时包括横纵坐标).
询问中点
(
m
i
d
,
m
i
d
)
(mid,mid)
(mid,mid) .
- 若距离为 0 0 0,说明有线经过该点,记录该位置并递归 s o l v e ( l , m i d − 1 ) , s o l v e ( m i d + 1 , r ) solve(l,mid-1),solve(mid+1,r) solve(l,mid−1),solve(mid+1,r)
- 若距离为 d ≠ 0 d\ne0 d=0,递归 s o l v e ( l , m i d − d ) , s o l v e ( m i d + d , r ) solve(l,mid-d),solve(mid+d,r) solve(l,mid−d),solve(mid+d,r)
最后,我们需要确定步骤一中得到的位置 ( p , p ) (p,p) (p,p) 经过的是竖线还是横线,记录之前任何一次询问不在线上的点的坐标为 ( n o , n o ) (no,no) (no,no),分别询问 ( n o , p ) (no,p) (no,p) 和 ( p , n o ) (p,no) (p,no) 即可.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
//#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e5+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,k;
int pl[N],tot;
int no;
int X[N],xx,Y[N],yy;
int o=1e8;
int debug(0);
void solve(int l,int r){
if(debug) printf("solve:(%d %d)\n",l,r);
if(l>r) return;
int mid=(l+r)/2;
printf("0 %d %d\n",mid,mid);fflush(stdout);
int d=read();
if(d==0){
if(debug) printf(" ok\n");
pl[++tot]=mid;
solve(l,mid-1);
solve(mid+1,r);
}
else{
no=mid;
if(debug) printf(" ??\n");
solve(l,mid-d);solve(mid+d,r);
}
return;
}
signed main(){
#ifndef ONLINE_JUDGE
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
#endif
solve(-o,o);
if(debug) printf("tot=%d no=%d\n",tot,no);
for(int i=1;i<=tot;i++){
int p=pl[i];
printf("0 %d %d\n",no,p);fflush(stdout);
if(!read()) Y[++yy]=p;
printf("0 %d %d\n",p,no);fflush(stdout);
if(!read()) X[++xx]=p;
}
printf("1 %d %d\n",xx,yy);
for(int i=1;i<=xx;i++) printf("%d ",X[i]);
putchar('\n');
for(int i=1;i<=yy;i++) printf("%d ",Y[i]);
return 0;
}
/*
*/
CF788E New task
Description \text{Description} Description
有一个长度为
n
n
n 的数列
a
i
a_i
ai,第
i
i
i 个数有一个零一属性
b
i
b_i
bi,初始所有的
b
b
b 都为
1
1
1.
m
m
m 次操作,分为两种:
1 x 1 \space x 1 x :令 b x = 0 b_x=0 bx=0.
2 x 2 \space x 2 x :令 b x = 1 b_x=1 bx=1
每次操作后输出满足条件的
p
1
<
p
2
<
p
3
<
p
4
<
p
5
p_1<p_2<p_3<p_4<p_5
p1<p2<p3<p4<p5,满足
a
p
1
≤
a
p
2
=
a
p
3
=
a
p
4
≥
a
p
5
a_{p_1} \le a_{p_2} =a_{p_3}=a_{p_4} \ge a_{p_5}
ap1≤ap2=ap3=ap4≥ap5 且
b
p
2
=
b
p
3
=
b
p
4
=
1
b_{p_2}=b_{p_3}=b_{p_4}=1
bp2=bp3=bp4=1 的个数.
对
1
0
9
+
7
10^9+7
109+7 取模的值.
(保证每次修改后的
b
i
b_i
bi 都与原来不同)
Solution \text{Solution} Solution
很适合练手的数据结构题.
一开始只想到树套树死卡空间然后被 @24KH 一语点破根本不用套.%%%
本题的关键就是动态统计加入一个点的贡献.
设
l
i
l_i
li 表示满足
j
<
i
,
a
j
≤
a
i
j<i,a_j\le a_i
j<i,aj≤ai 的
j
j
j 的个数.
r
i
r_i
ri 表示满足
j
>
i
,
a
j
≤
a
i
j>i,a_j\le a_i
j>i,aj≤ai 的
j
j
j 的个数.
那么我们考虑加入一个点
p
p
p 时的贡献:
p 作为中间元素
增加的方案数为:
∑
i
<
p
<
j
∧
a
i
=
a
p
=
a
j
l
i
×
r
j
\large \sum_{i<p<j \land a_i=a_p=a_j}l_i\times r_j
i<p<j∧ai=ap=aj∑li×rj
也就是:
∑
i
<
p
∧
a
i
=
a
p
l
i
×
∑
j
>
p
∧
a
j
=
a
p
r
j
\large \sum_{i<p \land a_i=a_p}l_i\times \sum_{j>p \land a_j=a_p}r_j
i<p∧ai=ap∑li×j>p∧aj=ap∑rj
p 作为两端元素
由于对称,单举
p
p
p 在最左侧为例.
增加的方案数为:
∑
p
<
i
∧
a
i
=
a
p
l
p
×
r
i
×
∑
p
<
j
<
i
[
a
j
=
a
p
]
\large \sum_{p<i\land a_i=a_p}l_p\times r_i\times\sum_{p<j<i}[a_j=a_p]
p<i∧ai=ap∑lp×ri×p<j<i∑[aj=ap]
换句话说就是
(
p
,
i
)
(p,i)
(p,i) 之间每有一个权值相等的点,
(
p
,
i
)
(p,i)
(p,i) 作为相等的两端就能产生一次贡献.
统计
离散化后对每个权值建一棵线段树.
∑
l
i
/
r
i
\sum l_i/r_i
∑li/ri 统计较为简单.
比较困难的就是统计:
∑
p
<
i
∧
a
i
=
a
p
r
i
×
∑
p
<
j
<
i
[
a
j
=
a
p
]
\large \sum_{p<i\land a_i=a_p}r_i\times\sum_{p<j<i}[a_j=a_p]
p<i∧ai=ap∑ri×p<j<i∑[aj=ap]
这一项.
设
r
a
n
s
rans
rans 为这一项的答案,
l
a
n
s
lans
lans 为这一项对称的答案,同时记录数的个数
s
i
z
siz
siz,
∑
l
i
,
∑
r
i
\sum l_i,\sum r_i
∑li,∑ri
合并左右儿子时:
s
i
z
l
s
+
s
i
z
r
s
→
s
i
z
f
a
siz_{ls}+siz_{rs}\to siz_{fa}
sizls+sizrs→sizfa
l
s
u
m
l
s
+
l
s
u
m
r
s
→
l
s
u
m
f
a
lsum_{ls}+lsum_{rs}\to lsum_{fa}
lsumls+lsumrs→lsumfa
r
s
u
m
l
s
+
r
s
u
m
r
s
→
r
s
u
m
f
a
rsum_{ls}+rsum_{rs}\to rsum_{fa}
rsumls+rsumrs→rsumfa
l
a
n
s
l
s
+
l
a
n
s
r
s
+
l
s
u
m
l
s
×
s
i
z
r
s
→
l
a
n
s
f
a
lans_{ls}+lans_{rs}+lsum_{ls}\times siz_{rs}\to lans_{fa}
lansls+lansrs+lsumls×sizrs→lansfa
r
a
n
s
l
s
+
r
a
n
s
r
s
+
r
s
u
m
r
s
×
s
i
z
l
s
→
r
a
n
s
f
a
rans_{ls}+rans_{rs}+rsum_{rs}\times siz_{ls}\to rans_{fa}
ransls+ransrs+rsumrs×sizls→ransfa
即可.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e5+100;
const int mod=1e9+7;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
ll le[N],ri[N];
int id[N],bac[N];
#define mid ((l+r)>>1)
struct node{
ll siz;
ll lsum,rsum;
ll lans,rans;
};
node merge(node a,node b){
return (node){a.siz+b.siz,(a.lsum+b.lsum)%mod,(a.rsum+b.rsum)%mod,
(a.lans+b.lans+a.lsum*b.siz)%mod,(a.rans+b.rans+a.siz*b.rsum)%mod};
}
struct tree{
node o;
int ls,rs;
}tr[N<<5];
int rt[N],tot;
inline int copy(int x){
++tot;tr[tot]=tr[x];
return tot;
}
void add(int &k,int l,int r,int p,int w){
if(!k) k=copy(k);
if(l==r){
tr[k].o.siz+=w;
tr[k].o.lsum+=w*le[l];
tr[k].o.rsum+=w*ri[l];
return;
}
if(p<=mid) add(tr[k].ls,l,mid,p,w);
else add(tr[k].rs,mid+1,r,p,w);
tr[k].o=merge(tr[tr[k].ls].o,tr[tr[k].rs].o);
//printf(" k=%d (%d %d) l")
}
//op=1:lsum
//op=2:lans
//op=3:rsum
//op=4:rans
node ask(int k,int l,int r,int x,int y){
if(!k||x>y) return (node){0,0,0,0,0};
if(x<=l&&r<=y) return tr[k].o;
if(y<=mid) return ask(tr[k].ls,l,mid,x,y);
else if(x>mid) return ask(tr[k].rs,mid+1,r,x,y);
else return merge(ask(tr[k].ls,l,mid,x,y),ask(tr[k].rs,mid+1,r,x,y));
}
int q[N],cnt,a[N];
int f[N];
inline void Add(int p){
for(;p<=cnt;p+=p&-p) ++f[p];
return;
}
inline int Ask(int p){
int res(0);
for(;p;p-=p&-p) res+=f[p];
return res;
}
inline ll calc(int pl){
int o=rt[a[pl]];
node L=ask(o,1,n,1,pl-1),R=ask(o,1,n,pl+1,n);
return (L.lsum*R.rsum%mod+L.lans*ri[pl]%mod+R.rans*le[pl]%mod)%mod;
}
ll tt;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=1;i<=n;i++) q[i]=a[i]=read();
sort(q+1,q+1+n);
cnt=unique(q+1,q+1+n)-q-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(q+1,q+1+cnt,a[i])-q;
for(int i=1;i<=n;i++){
le[i]=Ask(a[i]);Add(a[i]);
}
memset(f,0,sizeof(f));
for(int i=n;i>=1;i--){
ri[i]=Ask(a[i]);Add(a[i]);
}
for(int i=1;i<=n;i++) id[i]=++bac[a[i]];
//for(int i=1;i<=n;i++) printf("i=%d a=%d le=%lld ri=%lld id=%d\n",i,a[i],le[i],ri[i],id[i]);
for(int i=1;i<=n;i++){
tt+=calc(i);tt%=mod;
add(rt[a[i]],1,n,i,1);
}
m=read();
for(int i=1;i<=m;i++){
int op=read(),x=read();
if(op==1){
add(rt[a[x]],1,n,x,-1);tt-=calc(x);
}
else{
tt+=calc(x);add(rt[a[x]],1,n,x,1);
}
tt+=mod;tt%=mod;
printf("%lld\n",tt);
}
return 0;
}
/*
*/