设
u
p
x
up_x
upx 表示
x
x
x 连向其父结点的那条边的权值,
f
x
,
0
/
1
f_{x,0/1}
fx,0/1 表示令
w
n
x
wn_x
wnx 小于等于/大于等于
u
p
x
up_x
upx 时,将以
x
x
x 为根的子树中所有结点的
w
n
wn
wn 全部修改为合法的最小代价。
将
x
x
x 的所有子结点
y
y
y 按照
u
p
y
up_y
upy 从小到大排序,
u
p
y
up_y
upy 和
u
p
x
up_x
upx 将
w
n
x
wn_x
wnx 的取值划分成若干区间,取值在区间内部的决策是唯一的,不难得到转移。
另外当
w
n
x
wn_x
wnx 取
u
p
y
up_y
upy 时,可能会有多个
y
y
y 的
u
p
y
up_y
upy 相同,此时它们的
f
y
,
0
,
f
y
,
1
f_{y,0},f_{y,1}
fy,0,fy,1 均是有意义的,需要特殊处理。
两种情况均可以用前缀和优化,时间复杂度
O
(
n
log
n
)
\mathcal O(n \log n)
O(nlogn)。
#include<bits/st dc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =1e5+5;constint N2 =2e5+5;const ll Maxn =1e18;constint mod =998244353;int T_data, n, cm, mx =1e6;int wn[N], fa[N], c[N], cur[N], up[N];
ll f[N][2], pre[N], suf[N], sum[N];structarc{int to, cst;
arc *nxt;}p[N2],*adj[N],*T = p;inlinevoidlinkArc(int x,int y,int w){(++T)->nxt = adj[x]; adj[x]= T; T->to = y; T->cst = w;(++T)->nxt = adj[y]; adj[y]= T; T->to = x; T->cst = w;}inlineintcalc(int x,int l,int r){if(x >= l && x <= r)return0;return x < l ? l - x : x - r;}inlineboolcmp(constint&x,constint&y){return up[x]< up[y];}inlinevoiddfs(int x){for(arc *e = adj[x]; e; e = e->nxt){int y = e->to;if(y == fa[x])continue;
fa[y]= x;
up[y]= e->cst;dfs(y);}
cm =0;for(arc *e = adj[x]; e; e = e->nxt){int y = e->to;if(y == fa[x])continue;
cur[++cm]= y;}if(!cm){
f[x][0]=1ll* c[x]*calc(wn[x],0, up[x]);
f[x][1]=1ll* c[x]*calc(wn[x], up[x], mx +1);}else{
std::sort(cur +1, cur + cm +1, cmp);
up[cur[0]=0]=0;
up[cur[cm +1]= n +1]= mx +1;
pre[0]=0;for(int i =1; i <= cm;++i)
pre[i]= pre[i -1]+ f[cur[i]][0];
suf[cm +1]=0;for(int i = cm; i >=1;--i)
suf[i]= suf[i +1]+ f[cur[i]][1];
sum[0]=0;for(int i =1; i <= cm;++i)
sum[i]= sum[i -1]+Min(f[cur[i]][0], f[cur[i]][1]);for(int i =1; i <= cm +1;++i){if(up[cur[i -1]]<= up[x])CkMin(f[x][0], pre[i -1]+ suf[i]+1ll* c[x]*calc(wn[x], up[cur[i -1]],Min(up[cur[i]], up[x])));if(up[cur[i]]>= up[x])CkMin(f[x][1], pre[i -1]+ suf[i]+1ll* c[x]*calc(wn[x],Max(up[cur[i -1]], up[x]), up[cur[i]]));}for(int l =1, r =1; l <= cm; l = r +1){
r = l;while(r < cm && up[cur[r +1]]== up[cur[r]])++r;if(up[cur[r]]<= up[x])CkMin(f[x][0], pre[l -1]+ suf[r +1]+ sum[r]- sum[l -1]+1ll* c[x]*Abs(wn[x]- up[cur[r]]));if(up[cur[r]]>= up[x])CkMin(f[x][1], pre[l -1]+ suf[r +1]+ sum[r]- sum[l -1]+1ll* c[x]*Abs(wn[x]- up[cur[r]]));}}}intmain(){read(T_data);for(int t =1; t <= T_data;++t){read(n);for(int i =1; i <= n;++i)
f[i][0]= f[i][1]= Maxn;for(int i =1; i <= n;++i)read(c[i]);for(int i =1; i <= n;++i)read(wn[i]);for(int i =1, x, y, z; i < n;++i){read(x);read(y);read(z);linkArc(x, y, z);}
fa[1]=0;
up[1]= wn[1];dfs(1);put(Min(f[1][0], f[1][1])),putchar('\n');
up[n +1]= up[0]=0;for(int i =1; i <= n;++i)
adj[i]=NULL, up[i]= fa[i]=0;
T = p;}return0;}
设
[
L
i
,
R
i
]
[L_i,R_i]
[Li,Ri] 表示从点
i
i
i 出发最远能走到的区间范围,预处理
L
i
,
R
i
L_i,R_i
Li,Ri 则可
O
(
1
)
\mathcal O(1)
O(1) 回答询问。
先倒序循环
i
i
i,计算出从点
i
i
i 出发一直向右走最远能走到哪里,先存在
R
i
R_i
Ri 内,计算的过程相当于合并连续段,因此总移动次数
O
(
n
)
\mathcal O(n)
O(n)。
正序循环
i
i
i,计算
L
i
,
R
i
L_i,R_i
Li,Ri,具体分情况讨论:
当
R
i
−
1
≥
i
R_{i - 1} \ge i
Ri−1≥i 时,若从
[
i
,
R
i
]
[i,R_i]
[i,Ri] 可以往回走到
i
−
1
i - 1
i−1,则直接令
L
i
=
L
i
−
1
,
R
i
=
R
i
−
1
L_i = L_{i - 1},R_{i} = R_{i - 1}
Li=Li−1,Ri=Ri−1,否则直接令
L
i
=
i
L_i = i
Li=i,
R
i
R_i
Ri 为预处理的值。
当
R
i
−
1
<
i
R_{i - 1} < i
Ri−1<i 时,此时有
R
i
>
R
i
−
1
R_i > R_{i - 1}
Ri>Ri−1,暴力移动求
L
i
,
R
i
L_i,R_i
Li,Ri,计算
L
i
L_i
Li 的过程也相当于合并连续段,且
R
i
R_i
Ri 尝试移动的次数和
L
i
L_i
Li 相同,因此两者的总移动次数均为
O
(
n
)
\mathcal O(n)
O(n)。
判断区间内是否存在某个质因子可在 vector 上二分,时间复杂度
O
(
n
log
n
)
\mathcal O(n\log n)
O(nlogn)。
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;typedef vector<int>::iterator it;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =2e5+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n, m, pn, tis, lim =2e5;int a[N], b[N], l[N], r[N];int vis[N], low[N], pri[N];
vector<int> e[N];inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}inlinevoidsieve(){for(int i =2; i <= lim;++i){if(!low[i])
pri[++pn]= low[i]= i;for(int j =1; j <= pn &&1ll* i * pri[j]<= lim;++j){
low[i * pri[j]]= pri[j];if(low[i]== pri[j])break;}}}inlinevoidinsert(int x,int p){if(vis[x]!= tis){
vis[x]= tis;
e[x].clear();}
e[x].push_back(p);}inlineboolcheck(int x,int l,int r){
it p = std::lower_bound(e[x].begin(), e[x].end(), l);if(p == e[x].end())returnfalse;return e[x][p - e[x].begin()]<= r;}intmain(){sieve();read(T_data);while(T_data--){++tis;read(n);read(m);for(int i =1; i <= n;++i)read(a[i]);for(int i =1; i < n;++i)read(b[i]);for(int i =1; i <= n;++i){int x = a[i];while(low[x]>1){insert(low[x], i);
x /= low[x];}}for(int i = n; i >=1;--i){
r[i]= i;while(r[i]< n &&check(b[r[i]], i, r[i]))
r[i]= r[r[i]+1];}for(int i =1; i <= n;++i)if(i >1&& r[i -1]>= i){if(check(b[i -1], i, r[i])){
l[i]= l[i -1];
r[i]= r[i -1];}else
l[i]= i;}else{
l[i]= i;bool flag =true;while(flag){
flag =false;while(l[i]>1&&check(b[l[i]-1], l[i], r[i])){
flag =true;
l[i]= l[l[i]-1];}while(r[i]< n &&check(b[r[i]], l[i], r[i])){
flag =true;
r[i]= r[r[i]+1];}}}int x, y;while(m--){read(x);read(y);if(l[x]<= y && y <= r[x])puts("Yes");elseputs("No");}}return0;}
取边
(
i
,
i
+
1
)
(i,i+1)
(i,i+1) 构成一棵生成树,则得到的生成树内每条边的边权都小于等于
n
−
1
n - 1
n−1。
由
Kruskal
\text{Kruskal}
Kruskal 算法,最小生成树每条边的边权也小于等于
n
−
1
n - 1
n−1。
因此
∣
i
−
j
∣
|i - j|
∣i−j∣ 和
∣
p
i
−
p
j
∣
|p_i - p_j|
∣pi−pj∣ 至少有一项小于等于
n
−
1
\sqrt{n - 1}
n−1,总边数
O
(
n
n
)
\mathcal O(n\sqrt n)
O(nn)。
桶排后用
Kruskal
\text{Kruskal}
Kruskal 算法求最小生成树即可。
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;typedef pair<int,int> pir;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =1e5+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n, S;int fa[N], q[N], p[N];
vector<pir> v[N];
ll ans;inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}inlineboolcmp(constint&x,constint&y){return p[x]< p[y];}inlineintufs_find(int x){if(fa[x]!= x)return fa[x]=ufs_find(fa[x]);return x;}intmain(){read(T_data);while(T_data--){read(n);
S =sqrt(n -1);for(int i =1; i <= n;++i)read(p[i]);if(n ==1){puts("0");continue;}for(int i =1; i <= n;++i)
q[i]= i;
std::sort(q +1, q + n +1, cmp);for(int i =1; i < n;++i)for(int j = i +1, jm =Min(i + S, n); j <= jm;++j){
ll z =(j - i)*Abs(p[j]- p[i]);if(z <= n -1)
v[z].push_back(std::make_pair(i, j));
z =(j - i)*Abs(q[j]- q[i]);if(z <= n -1)
v[z].push_back(std::make_pair(q[i], q[j]));}for(int i =1; i <= n;++i)
fa[i]= i;
ans =0;for(int i =1; i < n;++i){for(pir e : v[i]){int tx =ufs_find(e.first),
ty =ufs_find(e.second);if(fa[tx]!= ty){
fa[tx]= ty;
ans += i;}}
v[i].clear();}put(ans),putchar('\n');}return0;}
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =1e5+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n;int pos[N], a[N], b[N];
map<int,int> cnt;inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}inlineboolcmp(constint&x,constint&y){return b[x]< b[y];}intmain(){read(T_data);while(T_data--){read(n);
cnt.clear();bool flag =false;for(int i =1; i <= n;++i){read(a[i]);if(++cnt[a[i]]>2)
flag =true;}if(flag)puts("NO");else{puts("YES");for(int i =1; i <= n;++i){
b[i]=0;for(int j =0; j <30;++j)if(a[i]>> j &1)
b[i]|=(1<<(29- j));}for(int i =1; i <= n;++i)
pos[i]= i;
std::sort(pos +1, pos + n +1, cmp);for(int i =1; i <= n;++i)put(a[pos[i]]),putchar(' ');puts("");}}return0;}
暴力分块,对于每一块,记
l
i
m
=
∑
a
i
在块内且
a
i
<
0
∣
a
i
∣
lim = \sum \limits_{a_i 在块内且 a_i < 0}|a_i|
lim=ai在块内且ai<0∑∣ai∣,预处理块内
[
0
,
l
i
m
]
[0, lim]
[0,lim] 的答案,询问时不完整块直接暴力,完整块直接用预处理的结果,大于
l
i
m
lim
lim 时的迭代过程显然和
l
i
m
lim
lim 相同。
时间复杂度
O
(
q
n
+
n
∑
i
=
1
n
∣
a
i
∣
)
\mathcal O(q\sqrt n + \sqrt n \sum\limits_{i = 1}^{n}|a_i|)
O(qn+ni=1∑n∣ai∣)。
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =5e5+5;constint L =1e3+5;constint M =1e6+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n, q, S, p[M];int len[L], a[N], bel[N], bl[L], br[L];int*ans[L],*now = p;inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}inlineintQuery(int l,int r,int x){int tl = bel[l], tr = bel[r];if(tl == tr){int res = x;for(int i = l; i <= r;++i)if(res + a[i]>=0)
res += a[i];return res;}
l == bl[tl]?--tl :0;
r == br[tr]?++tr :0;int res = x;for(int i = l; i <= br[tl];++i)if(res + a[i]>=0)
res += a[i];for(int i = tl +1; i < tr;++i)if(res <= len[i])
res = ans[i][res];else
res = ans[i][len[i]]+ res - len[i];for(int i = bl[tr]; i <= r;++i)if(res + a[i]>=0)
res += a[i];return res;}intmain(){read(T_data);while(T_data--){read(n);read(q);
S =sqrt(n);
bl[0]= br[0]=0;for(int i =1; i <= n;++i){
bel[i]=(i -1)/ S +1;if(!bl[bel[i]])
bl[bel[i]]= i;
br[bel[i]]= i;}
bl[bel[n]+1]= br[bel[n]+1]= n +1;for(int i =1; i <= n;++i)read(a[i]);
now = p;for(int i =1; i <= bel[n];++i){
len[i]=0;for(int j = bl[i]; j <= br[i];++j)if(a[j]<0) len[i]-= a[j];
ans[i]= now;
now += len[i]+1;for(int j =0; j <= len[i];++j){
ans[i][j]= j;for(int k = bl[i]; k <= br[i];++k)if(ans[i][j]+ a[k]>=0)
ans[i][j]+= a[k];}}int l, r, x;while(q--){read(l);read(r);read(x);++l;put(l > r ? x :Query(l, r, x)),putchar('\n');}for(int i =0; i <= bel[n]+1;++i)
bl[i]= br[i]=0;}return0;}
设
f
i
,
j
f_{i,j}
fi,j 表示将前
i
i
i 个元素划分成
j
j
j 个子序列的方案数。
转移分为以第
i
i
i 个元素新建一个子序列和将第
i
i
i 个元素插入到已有的子序列的末尾,对于第二种转移,设
p
r
e
i
pre_i
prei 表示最大的
k
k
k 满足
a
i
−
a
k
≥
r
a_i - a_k \ge r
ai−ak≥r,则
[
p
r
e
i
+
1
,
i
−
1
]
[pre_i + 1, i - 1]
[prei+1,i−1] 内的元素都恰好属于某一个子序列,且
i
i
i 无法再接在这些子序列后,不难得到转移。
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =5e3+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n, k, r;int a[N], pre[N];int f[N][N];inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}intmain(){read(T_data);while(T_data--){read(n);read(k);read(r);for(int i =1; i <= n;++i)read(a[i]);for(int i =1; i <= n;++i){
pre[i]= pre[i -1];while(pre[i]+1< i && a[i]- a[pre[i]+1]>= r)++pre[i];}for(int i =0; i <= n;++i)for(int j =0; j <= k;++j)
f[i][j]=0;
f[0][0]=1;for(int i =1; i <= n;++i)for(int j =1, jm =Min(i, k); j <= jm;++j){add(f[i][j], f[i -1][j -1]);if(pre[i])
f[i][j]=(1ll*Max(j -(i - pre[i]-1),0)* f[i -1][j]+ f[i][j])% mod;}put(f[n][k]),putchar('\n');}return0;}
不难发现答案不超过 2,问题即为
[
1
,
n
]
[1, n]
[1,n] 与
u
,
v
u,v
u,v 均互质的个数。
可转化为
[
1
,
n
]
[1,n]
[1,n] 内与
u
,
v
u,v
u,v 的所有出现过的素因子均互质的个数,素因子最多不超过 12 个,直接暴力枚举子集容斥即可。
#include<bits/stdc++.h>typedeflonglong ll;constint N =1e7+3;constint M =1e5+5;int pri[N], low[N];int n, u, v, tot, q;int p[M];bool size[N];
ll sum[N];inlinevoidsieve(int lim){int pn =0;for(int i =2; i <= lim;++i){if(!low[i])
pri[++pn]= low[i]= i;for(int j =1; j <= pn &&1ll* i * pri[j]<= lim;++j){
low[i * pri[j]]= pri[j];if(low[i]== pri[j])break;}}}inlineintread(){int v =0, c =1;char ch =getchar();while(!isdigit(ch)){if(ch =='-') c =-1;
ch =getchar();}while(isdigit(ch)){
v = v *10+ ch -48;
ch =getchar();}return v * c;}inlinevoidwork(int x){while(x !=1){int t = low[x];
p[++tot]= low[x];while(x % t ==0)
x /= t;}}intmain(){
n =read(), q =read();sieve(n);while(q--){
ll ans =0;
tot =0;
u =read(), v =read();int gc = std::__gcd(u,v);if(gc ==1){printf("1 1\n");continue;}
ans += gc ==2;work(u);work(v);
std::sort(p +1, p + tot +1);
tot = std::unique(p +1, p + tot +1)- p -1;constint C =1<< tot;for(int i =0; i < tot;++i)
sum[1<< i]= p[i +1], size[1<< i]=1;
ans += n;for(int i =1; i < C;++i){int t = i &-i;if(t != i){
sum[i]=1ll* sum[i ^ t]* sum[t];
size[i]= size[i ^ t]^1;}
size[i]? ans -=1ll* n / sum[i]: ans +=1ll* n / sum[i];}printf("2 %d\n",ans);}return0;}
设从第
n
n
n 个人的家运往第 1 个人的家的苹果数量为
x
x
x,则其余道路运送的苹果数量均能确定。
设
a
i
=
∑
j
=
1
i
(
e
j
−
b
j
)
a_i = \sum \limits_{j = 1}^{i}(e_j - b_j)
ai=j=1∑i(ej−bj),则总代价为
∑
i
=
1
n
l
i
∣
x
−
a
i
∣
\sum \limits_{i = 1}^{n}l_i |x - a_i|
i=1∑nli∣x−ai∣。
显然代价最小时
x
x
x 取的是
a
i
a_i
ai 的加权中位数,将
a
i
a_i
ai 离散化用线段树维护即可。
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::complex;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;typedef complex<ld> com;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =5e5+5;constint N4 =2e6+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;int T_data, n, q, cm;int b[N], e[N], l[N], a[N], c[N];
ll num[N], cnt[N4], sum[N4];
ll ans, cnt0, cnt1, sum0, sum1, tot;inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}#definesLs <<1#definesRs <<1|1inlinevoidUpdate(int s){
cnt[s]= cnt[sL]+ cnt[sR];
sum[s]= sum[sL]+ sum[sR];}inlinevoidBuild(int s,int l,int r){if(l == r){
cnt[s]= num[l];
sum[s]= num[l]* c[l];return;}int mid = l + r >>1;Build(sL, l, mid);Build(sR, mid +1, r);Update(s);}inlinevoidModify(int s,int l,int r,int x){if(l == r){
cnt[s]= num[l];
sum[s]= num[l]* c[l];return;}int mid = l + r >>1;
x <= mid ?Modify(sL, l, mid, x):Modify(sR, mid +1, r, x);Update(s);}inlinevoidQuery(int s,int l,int r, ll k){if(l == r){
ans = c[l];return;}int mid = l + r >>1;if(k <= cnt[sL]){
cnt1 += cnt[sR];
sum1 += sum[sR];Query(sL, l, mid, k);}else{
cnt0 += cnt[sL];
sum0 += sum[sL];Query(sR, mid +1, r, k - cnt[sL]);}}inlinevoidClear(int s,int l,int r){
cnt[s]= sum[s]=0;if(l == r)return;int mid = l + r >>1;Build(sL, l, mid);Build(sR, mid +1, r);}inlinevoidcalc(){
cnt0 = cnt1 = sum0 = sum1 =0;Query(1,1, cm, tot +1>>1);put(cnt0 * ans - sum0
+ sum1 - cnt1 * ans),putchar('\n');}intmain(){read(T_data);while(T_data--){read(n);
cm = tot =0;for(int i =1; i <= n;++i){read(b[i]);read(e[i]);read(l[i]);
a[i]= e[i]- b[i]+ a[i -1];
c[++cm]= a[i];}
std::sort(c +1, c + cm +1);
cm = std::unique(c +1, c + cm +1)- c -1;for(int i =1; i <= n;++i){
a[i]= std::lower_bound(c +1, c + cm +1, a[i])- c;
num[a[i]]+= l[i];
tot += l[i];}Build(1,1, cm);calc();read(q);while(q--){int x, y;read(x);read(y);
tot -= l[x];
num[a[x]]-= l[x];
l[x]= y;
tot += l[x];
num[a[x]]+= l[x];Modify(1,1, cm, a[x]);calc();}Clear(1,1, cm);for(int i =1; i <= cm;++i)
num[i]=0;}return0;}
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}template<classT>inlinevoid_put(T x){if(x <0)
x =-x,putchar('-');put(x);}template<classT>inlinevoidCkMin(T &x, T y){x > y ? x = y :0;}template<classT>inlinevoidCkMax(T &x, T y){x < y ? x = y :0;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}template<classT>inline T Max(T x, T y){return x > y ? x : y;}template<classT>inline T Abs(T x){return x <0?-x : x;}template<classT>inline T Sqr(T x){return x * x;}using std::map;using std::set;using std::pair;using std::bitset;using std::string;using std::vector;using std::complex;using std::multiset;using std::priority_queue;typedeflonglong ll;typedeflongdouble ld;typedef complex<ld> com;const ld pi =acos(-1.0);const ld eps =1e-8;constint N =1e5+5;constint N2 =2e5+5;constint Maxn =1e9;constint Minn =-1e9;constint mod =998244353;constint inv2 =499122177;int T_data, n, tis;int ans[N], fans[N], dfn[N], c[N], idx[N], low[N], sze[N], fa[N];inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlinevoiddec(int&x,int y){
x -= y;
x <0? x += mod :0;}structarc{int to;
arc *nxt;}p[N2],*adj[N],*P = p;inlinevoidlinkArc(int x,int y){(++P)->nxt = adj[x]; adj[x]= P; P->to = y;(++P)->nxt = adj[y]; adj[y]= P; P->to = x;}inlinevoidModify(int x){for(; x <= n; x += x &-x)++c[x];}inlineintQuery(int x){int res =0;for(; x; x ^= x &-x)
res += c[x];return res;}inlinevoiddfs(int x){
sze[x]=1;
dfn[x]=++tis;
idx[tis]= x;for(arc *e = adj[x]; e; e = e->nxt){int y = e->to;if(y == fa[x])continue;
fa[y]= x;dfs(y);
sze[x]+= sze[y];}
low[x]= tis;}inlinevoidsegModify(int l,int r,int v){if(l > r)return;add(ans[l], v);dec(ans[r +1], v);}intmain(){read(T_data);while(T_data--){read(n);for(int i =1, x, y; i < n;++i){read(x);read(y);linkArc(x, y);}dfs(1);for(int i =1; i <= n;++i){int l0 =Query(low[i])-Query(dfn[i]-1),
l1 = i -1- l0,
g0 = sze[i]-1- l0,
g1 = n - i - g0;segModify(dfn[i], low[i],1ll*(l1 - g1 + mod)* inv2 % mod);for(arc *e = adj[i]; e; e = e->nxt){int y = e->to;if(y == fa[i])continue;
l0 =Query(low[y])-Query(dfn[y]-1);
g0 = sze[y]- l0;if(l0 != g0){int tmp =1ll*(l0 - g0 + mod)* inv2 % mod;segModify(1, dfn[y]-1, tmp);segModify(low[y]+1, n, tmp);}}Modify(dfn[i]);}int tmp =1ll*(n -1)* n /2% mod * inv2 % mod;for(int i =1; i <= n;++i){add(ans[i], ans[i -1]);int res = tmp;add(res, ans[i]);
fans[idx[i]]= res;}for(int i =1; i <= n;++i)put(fans[i]),putchar('\n');
tis =0;for(int i =0; i <= n +1;++i)
ans[i]= fans[i]=0;for(int i =1; i <= n;++i)
c[i]= fa[i]= idx[i]= sze[i]= dfn[i]= low[i]=0;for(int i =1; i <= n;++i)
adj[i]=NULL;
P = p;}return0;}