# 莫队算法专题

### BZOJ【2038】—— [2009国家集训队]小Z的袜子(hose)

Time Limit: 20 Sec Memory Limit: 259 MB

6 4

1 2 3 3 3 2

2 6

1 3

3 5

1 6

2/5

0/1

1/1

4/15

#### 【样例解释】

【数据规模和约定】

30%的数据中 N,M ≤ 5000；

60%的数据中 N,M ≤ 25000；

100%的数据中 N,M ≤ 50000，1 ≤ L < R ≤ N，Ci ≤ N。

#### Source

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long LL;

const int PL = 500;

typedef struct node
{
int L,R;

int Id ;

node(){}

node(int _L,int _R):L(_L),R(_R){}

bool operator < (const node &a)const\\区间分块
{
return (L/PL == a.L/PL) ? (R<a.R):(L/PL<a.L/PL);
}
}Section;

Section s[55000];

int a[55000];

LL ansm[55000];

LL ansd[55000];

int num[55000];

int main()
{
int n,m;

while(~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",&s[i].L,&s[i].R),s[i].Id = i;

sort(s+1,s+m+1);

LL sum = 0;

int l = 0,r = 1;

memset(num,0,sizeof(num));

for(int i = 1;i<=m;i++)
{
while(r<=s[i].R)
{
sum+=(num[a[r]]);

num[a[r]] ++;

r++;
}

while(r>s[i].R+1)
{
r--;

num[a[r]] --;

sum-=num[a[r]];

}

while(l<s[i].L-1)
{
l++;

num[a[l]]--;

sum-=num[a[l]];

}

while(l>=s[i].L)
{
sum+=num[a[l]];

num[a[l]]++;

l--;
}

ansm[s[i].Id] = sum;

ansd[s[i].Id] = (1LL*(s[i].R-s[i].L+1)*(s[i].R-s[i].L))/2;
}

for(int i =1;i<=m;i++)
{
if(ansm[i] ==0) printf("0/1\n");
else
{
LL g = __gcd(ansm[i],ansd[i]);

printf("%lld/%lld\n",ansm[i]/g,ansd[i]/g);
}
}
}
return 0;
}

### Codeforces 86D. Powerful array

time limit per test 5 seconds memory limit per test 256 megabytes

An array of positive integers a1,a2,...,an$a_1, a_2, ..., a_n$ is given. Let us consider its arbitrary subarray al,al+1...,ar$a_l, a_{l + 1}..., a_r$, where 1 ≤ l ≤ r ≤ n. For every positive integer s denote by Ks the number of occurrences of s into the subarray. We call the power of the subarray the sum of products Ks·Ks·s for every positive integer s. The sum contains only finite number of nonzero summands as the number of different values in the array is indeed finite.

You should calculate the power of t given subarrays.

#### Input

First line contains two integers n and t (1 ≤ n, t ≤ 200000) — the array length and the number of queries correspondingly.

Second line contains n positive integers ai (1 ≤ ai ≤ 106) — the elements of the array.

Next t lines contain two positive integers l, r (1 ≤ l ≤ r ≤ n) each — the indices of the left and the right ends of the corresponding subarray.

#### Output

Output t lines, the i-th line of the output should contain single positive integer — the power of the i-th query subarray.

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preferred to use cout stream (also you may use %I64d).

Input

3 2
1 2 1
1 2
1 3

Output

3
6

Input

8 3
1 1 2 2 1 3 1 1
2 7
1 6
2 7

Output

20
20
20

#### Note

Consider the following array (see the second sample) and its [2, 7] subarray (elements of the subarray are colored):
Then K1 = 3, K2 = 2, K3 = 1, so the power is equal to 32·1 + 22·2 + 12·3 = 20.

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int BO = 1000;

const int Max = 210000;

const int MaxM = 1e6+100;

typedef struct node
{
int L,R,Id;

bool operator < (const node &a)const
{
return (L/BO == a.L/BO)?(R<a.R) : (L/BO<a.L/BO);
}
}Section;

Section s[Max];

int a[Max];

LL num[MaxM];

LL ans[Max];

int main()
{
int n,m;

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",&s[i].L,&s[i].R),s[i].Id = i ;

sort(s+1,s+m+1);

memset(num,0,sizeof(num));

LL sum = 0;

int l  = 0,r=  1;

for(int i = 1;i<=m;i++)
{
while(r<=s[i].R)
{
sum+=((num[a[r]]*2+1)*a[r]);

num[a[r]] ++;

r++;
}
while(r>s[i].R+1)
{
r--;

sum-=((num[a[r]]*2-1)*a[r]);

num[a[r]]-- ;
}

while(l<s[i].L-1)
{
l++;

sum-=((num[a[l]]*2-1)*a[l]);

num[a[l]]-- ;
}

while(l>=s[i].L)
{
sum+=((num[a[l]]*2+1)*a[l]);

num[a[l]]++;

l--;
}

ans[s[i].Id] = sum;
}

for(int i = 1;i<=m;i++)
{
printf("%I64d\n",ans[i]);
}
return 0;
}

### Bzoj【 3289】—— Mato的文件管理

Time Limit: 40 Sec Memory Limit: 128 MB

#### Description

Mato同学从各路神犇以各种方式（你们懂的）收集了许多资料，这些资料一共有n份，每份有一个大小和一个编号。为了防止他人偷拷，这些资料都是加密过的，只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r]，他今天就看编号在此区间内的这些资料。Mato有一个习惯，他总是从文件大小从小到大看资料。他先把要看的文件按编号顺序依次拷贝出来，再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的文件（因为加密需要，不能随机访问）。Mato想要使文件交换次数最小，你能告诉他每天需要交换多少次吗？

#### Output

q行，每行一个正整数，表示Mato这天需要交换的次数。

4

1 4 2 3

2

1 2

2 4

0

2

Hint

n,q <= 50000

#### Source

By taorunz

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>

using namespace std;

typedef long long LL;

const int Bo = 400;

const int Max = 55000;

const int MaxN = 50000;

typedef struct node
{
int L,R,Id;

bool operator < (const node &a)const
{
return (L/Bo == a.L/Bo)?(R<a.R):(L/Bo<a.L/Bo);
}
}Section;

Section S[Max];

int Tr[Max];

int a[Max];

int b[Max];

LL ans[Max];

int n,m;

int Lowbite(int x) {return x&(-x);}

{
while(x<=MaxN)
{
Tr[x]+=va;

x+=Lowbite(x);
}
}

int  Qu(int x)
{
int ans = 0;

while(x>0)
{
ans+=Tr[x];

x-=Lowbite(x);
}

return ans;

}

int Search(int L,int R,int s)
{
while(L<=R)
{
int mid = (L+R)>>1;

if(b[mid] == s) return mid;

if(b[mid]<s) L = mid+1;

else R = mid-1;
}

return 0;
}

int main()
{
while(~scanf("%d",&n))
{
for(int i = 1;i<=n;i++) scanf("%d",&a[i]),b[i] = a[i];

sort(b+1,b+n+1);

b[0] = 1;

for(int i  = 1;i<=n;i++)
{
if(b[b[0]]!= b[i]) b[++b[0]] = b[i];
}

for(int i = 1;i<=n;i++)//离散化
{
a[i] = Search(1,b[0],a[i]);
}

scanf("%d",&m);

for(int i  =1;i<=m;i++) scanf("%d %d",&S[i].L,&S[i].R),S[i].Id = i;

sort(S+1,S+m+1);

memset(Tr,0,sizeof(Tr));

LL sum = 0;

int l = 0 ,r =  1;

for(int i  = 1;i<=m;i++)
{
while(r<=S[i].R)
{
sum+=Qu(MaxN)-Qu(a[r]);

r++;
}

while(r>S[i].R+1)
{
r--;

sum-=(Qu(MaxN)-Qu(a[r]));

}

while(l<S[i].L-1)
{
l++;

sum-=(Qu(a[l]-1));

}

while(l>=S[i].L)
{
sum+=(Qu(a[l]-1));

l--;
}

ans[S[i].Id] = sum;
}

for(int i  =1;i<=m;i++)
{
printf("%lld\n",ans[i]);
}

}
return 0;
}

### HDU【5381】——The sum of gcd

|Time Limit: 2000/1000 MS (Java/Others) | Memory Limit: 65536/65536 K (Java/Others)|

#### Problem Description

You have an array A,the length of A is n
Let  f(l,r)=i=lr j=irgcd(ai,ai+1,aj)$\ f(l,r) = \sum\limits_{i = l}^r \ \sum\limits_{j = i}^r gcd(a_i,a_{i+1} \cdots,a_j)$

#### Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers n
Second line has n integers Ai
Third line has one integers Q,the number of questions
Next there are Q lines,each line has two integers l,r
1≤T≤3
1≤n,Q≤104$^4$
1≤ai≤109$^9$
1≤l < r≤n

#### Output

For each question,you need to print f(l,r)

2
5
1 2 3 4 5
3
1 3
2 3
1 4
4
4 2 6 9
3
1 3
2 4
2 3

9
6
16
18
23
10

#### Author

SXYZ

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int Bo = 200;

const int Max = 1e4+100;

typedef struct node
{
int L,R,Id;

bool operator < (const node &a)const
{
return (L/Bo == a.L/Bo)?(R<a.R):(L/Bo<a.L/Bo);
}
}Section;

Section S[Max];

int n,m;

int rmq[Max][15];

int a[Max];

LL ans[Max];

vector<pair<int,int> >VL[Max];

vector<pair<int,int> >VR[Max];

int GCD(int a,int b)
{
return b == 0 ?a:GCD(b,a%b);
}
//用RMQ查询区间gcd，保证O（1）的查询
void GetRmq()
{
for(int i = 1;i<=n;i++)
rmq[i][0] = a[i];

for(int  i = 1;(1<<i)<=n;i++)
{
for(int j = 1;j<=n;j++)
{
if(j+(1<<i)-1<=n)
{
rmq[j][i] =GCD(rmq[j][i-1],rmq[j+(1<<(i-1))][i-1]);
}
}
}

}

int Qu(int l,int r)
{
int k = (int)log2(r-l+1);

return GCD(rmq[l][k],rmq[r-(1<<k)+1][k]);
}
//固定s为右端点，向左延伸gcd为t的最左端的位置
int RSearch(int s,int L,int R,int t)
{
int ans ;

while(L<=R)
{
int mid = (L+R)>>1;

if(Qu(mid,s) == t)
{
ans = mid;
R = mid-1;
}
else L = mid+1;
}
return ans;
}
//固定s为左端点，向右延伸gcd为t的最右端的位置
int LSearch(int s,int L,int R,int t)
{
int ans ;

while(L<=R)
{
int mid = (L+R)>>1;

if(Qu(s,mid) == t)
{
ans = mid;
L = mid+1;
}
else R= mid-1;
}
return ans;
}

LL Rcal(int s,int t)
{
LL ans = 0;

int ss = s;

for(int i = 0;i<VR[s].size();i++)
{

ans +=(1LL*(ss-max(t,VR[s][i].second)+1)*VR[s][i].first);

ss = VR[s][i].second-1;

if(ss<t) break;
}

return ans;
}

LL Lcal(int s,int t)
{
LL ans = 0;

int ss = s;

for(int i = 0;i<VL[s].size();i++)
{

ans+=(1LL*(min(t,VL[s][i].second)-ss+1)*VL[s][i].first);

ss = VL[s][i].second+1;

if(ss>t) break;
}

return ans;
}

int main()
{
int T;

freopen("in.in","r",stdin);

scanf("%d",&T);

while(T--)
{
scanf("%d",&n);

for(int i = 1;i<=n;i++) scanf("%d",&a[i]);

GetRmq()；

//处理出左端固定的不同gcd的区间段
for(int i = 1;i<=n;i++)
{
int r = i;

VL[i].clear();

while(r<=n)
{
int ant = Qu(i,r);

r = LSearch(i,r,n,ant);

VL[i].push_back(make_pair(ant,r));

r++;
}
}

for(int i =n;i>=1;i--)
{
int l = i;

VR[i].clear();

while(l>=1)
{
int ant = Qu(l,i);

l = RSearch(i,1,l,ant);

VR[i].push_back(make_pair(ant,l));

l--;
}
}

scanf("%d",&m);

for(int i = 1;i<=m;i++) scanf("%d %d",&S[i].L,&S[i].R) , S[i].Id = i;

sort(S+1,S+m+1);

LL sum = 0;

int l = 0,r = 1;

for(int i = 1;i<=m;i++)
{

while(r<=S[i].R)
{
sum+=Rcal(r,l+1);

r++;
}

while(r>S[i].R +1)
{

r --;

sum-=Rcal(r,l+1);
}

while(l<S[i].L-1)
{
l++;

sum-=Lcal(l,r-1);
}

while(l>=S[i].L)
{
sum+=Lcal(l,r-1);

l--;
}

ans[S[i].Id] = sum;
}

for(int i = 1;i<=m;i++) printf("%I64d\n",ans[i]);
}
return 0;
}

### Bzoj【4540】—— [Hnoi2016]序列

Time Limit: 20 Sec Memory Limit: 512 MB

#### Description

给定长度为n的序列：a1,a2,…,an，记为a[1:n]。类似地，a[l:r]（1≤l≤r≤N）是指序列：al,al+1,…,ar-
1,ar。若1≤l≤s≤t≤r≤n，则称a[s:t]是a[l:r]的子序列。现在有q个询问，每个询问给定两个数l和r，1≤l≤r
≤n，求a[l:r]的不同子序列的最小值之和。例如，给定序列5,2,4,1,3，询问给定的两个数为1和3，那么a[1:3]有
6个子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3]，这6个子序列的最小值之和为5+2+4+2+2+2=17。

#### Input

输入文件的第一行包含两个整数n和q，分别代表序列长度和询问数。接下来一行，包含n个整数，以空格隔开
,第i个整数为ai，即序列第i个元素的值。接下来q行，每行包含两个整数l和r，代表一次询问。

5 5

5 2 4 1 3

1 5

1 3

2 4

3 5

2 5

28

17

11

11

17

#### HINT

1 ≤N,Q ≤ 100000,|Ai| ≤ 109$10^9$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <algorithm>
#define rr() freopen("in.in","r",stdin)
#define ww() freopne("out.out","w",stdout)

using namespace std;

typedef long long LL;

const int Max = 110000;

int a[Max],rmq[Max][21];

int n,m,Bo;

LL sumL[Max],sumR[Max];

LL ans[Max];

int L[Max],R[Max];

stack<int>St;

typedef struct node
{
int L,R,Id;

bool operator < (const node &a)const
{
return (L/Bo == a.L/Bo)?R<a.R:(L/Bo<a.L/Bo);
}
}Section;

Section S[Max];
//RMQ处理区间最小值得查询，返回的为最小值的下标
void GetRmq()
{
for(int i = 1;i<=n;i++) rmq[i][0] = i;

for(int i  =1;(1<<i)<=n;i++)
for(int j =1;j+(1<<i)-1<=n;j++)
rmq[j][i] = a[rmq[j][i-1]]<a[rmq[j+(1<<(i-1))][i-1]]?rmq[j][i-1]:rmq[j+(1<<(i-1))][i-1];
}

int Qu(int L,int R)
{
int k =(int)log2(R-L+1);

return a[rmq[L][k]]<a[rmq[R-(1<<k)+1][k]] ? rmq[L][k]:rmq[R-(1<<k)+1][k];
}
//右边界的更新
LL Rcal(int l,int r)
{
int s = Qu(l+1,r);

return (1LL*(s-l)*a[s]+sumR[r]-sumR[s]);
}
//左边界的更新
LL Lcal(int l,int r)
{
int s = Qu(l,r-1);

return (1LL*(r-s)*a[s]+sumL[l]-sumL[s]);
}

int main()
{
while(~scanf("%d %d",&n,&m))
{
for(int i = 1;i<=n;i++) scanf("%d",&a[i]);

GetRmq(); Bo = (int)sqrt(n);

for(int i = 1;i <= m; i++) scanf("%d %d",&S[i].L,&S[i].R),S[i].Id = i;

sort(S+1,S+m+1);

St.push(0);
//单调栈处理出以每个点的为右边，区间最小值为对应点对值得最左边界
for(int i = 1;i <= n;i++)
{
while(St.size() > 1 && a[St.top()] > a[i]) St.pop();

R[i] = St.top(); St.push(i);
}

while(!St.empty()) St.pop();
//单调栈处理出以每个点的为左边，区间最小值为对应点对值得最右边界
St.push(n+1);

for(int i = n;i>=1;i--)
{
while(St.size() > 1 && a[St.top()] > a[i]) St.pop();

L[i] = St.top(); St.push(i);
}

while(!St.empty()) St.pop();

memset(sumL,0,sizeof(sumL));

memset(sumR,0,sizeof(sumR));

sumR[1] =a[1];

//处理树的前缀和。

for(int i = 2;i<=n;i++) sumR[i] = sumR[R[i]]+(1LL)*(i-R[i])*a[i];

sumL[n] = a[n];

for(int i = n-1;i >= 1;i--) sumL[i] = sumL[L[i]]+(1LL)*(L[i]-i)*a[i];

LL sum = 0;

int l = 0,r = 1;

for(int i = 1;i<=m;i++)
{
while(r <= S[i].R) sum +=Rcal(l,r),r++;

while(r > S[i].R+1) r --,sum-=Rcal(l,r);

while(l < S[i].L-1) l++,sum-=Lcal(l,r);

while(l >= S[i].L) sum+=Lcal(l,r),l--;

ans[S[i].Id] =sum;
}

for(int i = 1;i<=m;i++) printf("%lld\n",ans[i]);
}
return 0;
}

### Codeforces 617E. XOR and Favorite Number

time limit per test4 seconds memory limit per test256 megabytes

Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1, …, aj is equal to k.

#### Input

The first line of the input contains integers n, m and k (1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 1 000 000) — the length of the array, the number of queries and Bob’s favorite number respectively.

The second line contains n integers ai (0 ≤ ai ≤ 1 000 000) — Bob’s array.

Then m lines follow. The i-th line contains integers li and ri (1 ≤ li ≤ ri ≤ n) — the parameters of the i-th query.

#### Output

Print m lines, answer the queries in the order they appear in the input.

input
6 2 3
1 2 1 1 0 3
1 6
3 5
output
7
0
input
5 3 1
1 1 1 1 1
1 5
2 4
1 3
output
9
4
4

#### Note

In the first sample the suitable pairs of i and j for the first query are: (1, 2), (1, 4), (1, 5), (2, 3), (3, 6), (5, 6), (6, 6). Not a single of these pairs is suitable for the second query.

In the second sample xor equals 1 for all subarrays of an odd length.

#include <bits/stdc++.h>
#define rr() freopen("in.in","r",stdin)
#define ww() freopen("out.out","w",stdout)

using namespace std;

typedef long long LL;

const int Max=  1<<22;

int num[Max],Bo;

int pre[100100];

typedef struct node
{
int L,R,Id;

bool operator < (const node &a)const
{
return (L/Bo == a.L/Bo)?R<a.R:(L/Bo<a.L/Bo);
}
}Section;

Section S[100100];

LL ans[100100];

int main()
{
int n,data,m,k;

//rr();

scanf("%d %d %d",&n,&m,&k);

Bo = (int)sqrt(n);

pre[0] = 0;

for(int i =1;i<=n;i++)
{
scanf("%d",&data);

pre[i] = pre[i-1]^data;
}

for(int i = 1;i<=m;i++)
{
scanf("%d %d",&S[i].L,&S[i].R);

S[i].Id = i;
}

sort(S+1,S+m+1);

LL sum = 0;

int l = 0,r = 0;

memset(num,0,sizeof(num));

for(int i = 1;i<=m;i++)
{
while(r<=S[i].R)
{
sum+=num[pre[r]^k];

num[pre[r]]++;

r++;
}

while(r>S[i].R+1)
{
r--;

--num[pre[r]];

sum-=num[pre[r]^k];

}
while(l<S[i].L-1)
{

--num[pre[l]];

sum-=num[pre[l]^k];

l++;

}

while(l>=S[i].L)
{
l--;

sum+=num[pre[l]^k];

num[pre[l]]++;

}
ans[S[i].Id] = sum;
}

for(int i = 1;i<=m;i++) printf("%I64d\n",ans[i]);
return 0;
}

### Bzoj【1086】—— [SCOI2005]王室联邦

Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge

#### Description

“余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省，每个省都由他们王室联邦的一个成

#### Input

第一行包含两个数N，B（1<=N<=1000, 1 <= B <= N）。接下来N－1行，每行描述一条边，包含两个数，即这

#### Output

如果无法满足国王的要求，输出0。否则输出数K，表示你给出的划分方案中省的个数，编号为1..K。第二行输

8 2

1 2

2 3

1 8

8 7

8 6

4 6

6 5

#### Sample Output

3

2 1 1 3 3 3 3 2

2 1 8

VFlea King的讲解：首先以任意节点为根DFS，DFS的任务是解决以当前节点为根的子树（不包括当前节点）中的节点的归属，并汇报不知道去向何方者。具体做法是：对于每个正在处理的节点v，定义一个等待序列，扫一遍它的孩子。在扫的时候，假设当前for循环正在处理的是孩子u，DFS(u)，然后把传回来的等待序列加到v的等待序列中。如果v的等待序列节点数超过了B，那么就让等待队列中的节点组成一个省，省会是v，但v不划入那个省中。最后，for循环结束，把v加入到等待序列中，return。在主函数中接收DFS的返回值，若等待序列为空，皆大欢喜；但事实上，等待序列不可能为空。那么等待序列中的节点数一定不超过B + 1，怎么办？答案就是放在上一个被划分出的省中去，那么上一个被划分出的省一定<=2B - 1，而现在最后无家可归的节点数一定<= B + 1，所以放在上一个被划分出的省中去节点数一定不超过3B！而且最后被划分出来的省一定和最后无家可归的节点中的某一个相邻！”

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>

using namespace std;

int n,B,num;

int pre[1100];

int a[1100],b[1100];

vector<int>E[1100];

void Init(){
for(int i =1;i<=n;i++) E[i].clear();
}

int dfs(int u,int fa){

int size = 0;

for(int i = 0;i<E[u].size();i++)
{
if(E[u][i] == fa) continue;

size += dfs(E[u][i],u);

if(size >=B){
++num;

for(int i = a[0];i>a[0]-size;i--){
pre[a[i]] = num;
}
b[++b[0]] = u;

a[0] -=size;

size = 0;
}
}

size ++;

a[++a[0]] = u;

return size;
}

int main()
{
int u,v;

while(~scanf("%d %d",&n,&B)){
Init();

for(int i = 1;i<n;i++){
scanf("%d %d",&u,&v);

E[u].push_back(v);

E[v].push_back(u);
}

num = 0;

a[0] = 0; b[0] = 0;

int ans = dfs(1,0);

if(ans) {
for(int i = 1;i<=a[0];i++)
{
pre[a[i]] = num;
}
}

printf("%d\n",num);

if(num){
for(int i =1;i<=n;i++) {
if(i!=1) printf(" ");
printf("%d",pre[i]);
}

printf("\n");

for(int i = 1;i<=b[0];i++) {
if(i != 1) printf(" ");
printf("%d",b[i]);
}

printf("\n");
}
}
return 0;
}