E - Coprime
First,judging the
g
c
d
(
a
1
,
a
2
,
.
.
.
,
a
n
)
gcd(a_1,a_2,...,a_n)
gcd(a1,a2,...,an) whether equal to
1
1
1.
Then,if not equal to
1
1
1,output “not coprime”,else we judging whether is multiply number’s factory for every
<
=
1
e
6
<=1e6
<=1e6’ prime。
The problem can be solved in
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn).
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,a[N],tot,head[N],nex[N*10],to[N*10];
void add(int u,int v){to[++tot]=v;nex[tot]=head[u];head[u]=tot;}
bool vis[N];
int main()
{
for(int i=2;i<=1000000;i++)
if(!vis[i])
{
for(int j=i;j<=1000000;j+=i)
vis[j]=true,add(j,i);
}
scanf("%d",&n);
int ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),ans=__gcd(a[i],ans);
if(ans!=1) printf("not coprime\n");
else
{
memset(vis,false,sizeof(vis));
bool flag=false;
for(int i=1;i<=n&&!flag;i++)
for(int j=head[a[i]];j&&!flag;j=nex[j])
{
if(vis[to[j]]) flag=true;
vis[to[j]]=true;
}
if(flag) printf("setwise coprime\n");
else printf("pairwise coprime\n");
}
}
F I hate Shortest Path Problem
A bad idea
Depart from evey coordinate
(
1
,
i
)
(1,i)
(1,i),move row by row and column by column for each row。
Eevery time move from coordinate
(
i
,
j
)
(i,j)
(i,j) to somewhere,if not
a
i
<
=
j
<
=
b
i
a_i<=j<=b_i
ai<=j<=bi then find the minimize
k
k
k so that
k
>
i
k>i
k>i and
a
k
<
=
j
<
=
b
k
a_k<=j<=b_k
ak<=j<=bk(But this just find a way so that once query spend
O
(
l
o
g
2
n
)
O(log^2n)
O(log2n) time),then update the answer in section
[
i
,
k
−
1
]
[i,k-1]
[i,k−1] maintained by segment tree and in k-th row build a new coordinate
(
k
,
j
)
(k,j)
(k,j),else move to coordinate
(
i
,
b
i
+
1
)
(i,b_i+1)
(i,bi+1) and record the optimal distance cost。
The method is bad because I find not a way maintain once query in
O
(
l
o
g
n
)
O(logn)
O(logn) is step 2,total need
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n) times,is get TLE.
A good idea
We don’t need consider the cost in row move because we just can move to down or right,so that for a row the row moves step is fixed.
We just maintain arrived the i-th row,for each column,we arrive the column least need cost how many column moves.
We maintained by segment tree.We regard one row’s pair
a
i
,
b
i
a_i,b_i
ai,bi as a operation:query the cost move to the
a
i
−
1
a_i-1
ai−1 needed column moves
d
d
d,update the cost for every column
j
j
j(
a
i
<
=
j
<
=
b
i
a_i<=j<=b_i
ai<=j<=bi) to
j
−
(
a
i
−
1
)
+
d
j-(a_i-1)+d
j−(ai−1)+d.
Every time we arrived a row,we just query the minmum value moved to column j needed cost.
So that the problem can solved in
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,t[N<<2],t1[N<<2],t2[N<<2];
void update(int l,int r,int k)
{
t1[k]=t[k]+r-l;t2[k]=t[k];
if(l!=r)
{
int m=l+r>>1;
t[k<<1]=t[k];t[k<<1|1]=t[k]+m+1-l;
}
t[k]=0;
}
int query(int l,int r,int k,int x)
{
if(t[k]) update(l,r,k);
if(l>x) return m+1;
if(r<=x) return t1[k];
int m=l+r>>1;
int a=query(l,m,k<<1,x),b=query(m+1,r,k<<1|1,x);
if(x<=r) a+=x>=m?x-m:0;
else a+=r-m;
t2[k]=min(t2[k<<1],t2[k<<1|1]);
t1[k]=min(t1[k<<1]+r-m,t1[k<<1|1]);
return min(a,b);
}
void update(int l,int r,int k,int x,int y,int d)
{
if(t[k]) update(l,r,k);
if(r<x||l>y) return;
if(l>=x&&r<=y)
{
t[k]=d+l-x;
update(l,r,k);
return;
}
int m=l+r>>1;
update(l,m,k<<1,x,y,d);update(m+1,r,k<<1|1,x,y,d);
t2[k]=min(t2[k<<1],t2[k<<1|1]);
t1[k]=min(t1[k<<1]+r-m,t1[k<<1|1]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,a,b,d;i<=n;i++)
{
scanf("%d%d",&a,&b);
d=min(m+1,query(1,m,1,a-1)+1);
update(1,m,1,a,b,d);
printf("%d\n",t2[1]>=m?-1:t2[1]+i);
}
}