複習與回顧:2021.7.10 contest 3
複習與回顧:2021.7.10 contest 3
A
Description
Alice
和 Bob
在玩石頭剪刀布,他們每個人寫出一個序列。 Alice 寫出了 \(n\) 個數,Bob 寫出了 \(n\) 個數。
其中 \(0\) 代表石頭,\(1\) 代表剪刀,\(2\) 代表布 。
他們總共進行 \(k\) 輪遊戲,第一輪選擇第一個數字,後面每一輪兩個人都選擇序列的下一個數進行比賽(序列結尾的下一個位置在序列開頭)。
一個人的積分為其贏的次數加上額外積分。
額外積分:對於每一個 \([1,k-x+1]\) 內的正整數 ,滿足某人從第 \(i\) 輪到第 \(i+x-1\)
問
Alice
和 Bob
每人積分是多少。
Input
第一行三個數 \(n,m\) 。
第二行 \(n\) 個不大於 \(2\) 的非負整數。
第三行 \(m\) 個不大於 \(2\) 的非負整數。
Output
一行兩個整數表示 Alice
和 Bob
每人積分。
Example
input
5 10 2
1 1 0 2 0
1 0 2 2 0
output
0 6
Hint
滿足 \(1 \leq n \leq 5*10^5\ ,\ 1 \leq k,x \leq 10^{18}\)
Solution
由於兩人給出的序列長度都是 \(n\)
Alice
和 Bob
分別計算一遍
B
Description
有 \(t\) 次詢問,每次給你一個數 \(n\) ,求在 \([1,n]\) 內約數個數最多的數的約數個數。
Input
第一行一個正整數 \(t\) 。
之後 \(t\) 行,每行一個正整數 \(n\) 。
Output
輸出 \(t\) 行,每行一個整數,表示答案。
Example
input
5
13
9
1
13
16
output
6 4 1 6 6
Hint
滿足 \(t \leq 15\ ,\ 1 \leq n \leq 10^{18}\)
Solution
將 \(x \in [1,n]\) 進行質因數分解,則 \(x=\prod_{i=1}^{m}{p_i^{a_i}}\) ,而 \(x\) 的因數個數可表示為 \(\prod_{i=1}^{m}{(a_i+1)}\) ,發現與 \(p_i\) 大小無關,於是儘量把 \(p_i\) 往小取。
考慮爆搜,規定 \(p_i\) 與 \(p_{i+1}\) 是相鄰的質數且 \(p_i < p_{i+1}\) ,要求 \(a_i \geq a_{i+1}\) 。發現跑最大資料比較吃力,於是記錄 \(f_{i,j}\) 表示 \(p_i\) 為前 \(i\) 個質數,因數個數為 \(j\) 時的最小 \(x\) 來剪枝。
C
Description
給你一個長為 \(n\) 的序列 \(a\) 和一個常數 \(K\) 。
有 \(m\) 次詢問,每次查詢一個區間 \([l,r]\) 內所有數最少分成多少個連續段,使得每段的和都 \(\leq K\) 。
如果這一次查詢無解,輸出 "Chtholly",輸出的字串不包含引號。
Input
第一行三個數 \(n,m,K\) 。
第二行 \(n\) 個數表示這個序列 \(a\)。
之後 \(m\) 行,每行給出兩個數 \(l,r\) 表示一次詢問。
Output
輸出 \(m\) 行,每行一個整數,表示答案。
Example
input
5 5 7
2 3 2 3 4
3 3
4 4
5 5
1 5
2 4
output
1
1
1
2
2
Hint
滿足 \(1 \leq n,m \leq 10^6\ ,\ 1 \leq a_i,K \leq 10^9\) 。
Solution
考慮暴力,由於 \(a_i > 0\),從詢問左端點開始每次貪心地取最長的滿足限制的一段一定最優。發現除了最右的一段,每一段左端點對應的結束位置唯一確定,於是預處理後倍增加速這一過程,使複雜度降至 \(O((n+m)\,logn)\)
D
Description
給定一棵 \(n\) 個節點的樹,第 \(i\) 個點的編號為 ,第 \(j\) 條邊的編號為 \(j\) 。
有 \(m\) 次查詢,每次給出 \(l,r\) ,查詢如果只保留樹上點編號在 \([l,r]\) 內的點,邊編號在 \([l,r]\) 內的邊,有多少點連通塊,此時點 \(a\) 與 \(b\) 連通等價於 \(l \leq a,b \leq r\) 且 \(a,b\) 在樹上的簡單路徑中所有點與邊編號都在 \([l,r]\)之間。
Input
第一行兩個數 \(n,m\) 。
之後 \(n-1\) 行,編號從 \(1\) 開始,第 \(i\) 行兩個數 \(x,y\) 表示編號為 \(i\) 的邊連線著點 。
之後 \(m\) 行,每行兩個數 \([l,r]\) 表示詢問區間 。
Output
對每次詢問輸出一行一個數表示答案。
Example
input
10 10
1 2
2 3
1 4
1 5
6 4
7 2
8 3
1 9
3 10
1 6
6 7
1 8
3 3
7 10
4 10
8 9
2 3
5 8
5 9
output
1
2
1
1
4
6
2
1
4
5
Hint
滿足 \(1 \leq n,m \leq 10^6\)
Solution
對於一棵樹的一個頂點子集\(V\)和邊子集\(E\),定義一條邊 \((u,v)\)為有效邊當且僅當 \((u,v) \in E\ \ \bigwedge\ \ u,v \in V\) ,設有效邊集合為 \(e\) ,則樹的子圖\(G=<V,E>\) 中的連通塊個數等於 \(|V|-|e|\) ,證明顯然。
對於詢問區間 \([l,r]\ ,\ |V|=r-l+1\) 於是只需求 \(|e|\)
考慮編號 \(w\) 的邊 \((u,v)\) ,其產生貢獻當: \(l \leq w,u,v \leq r\ \ \Longleftrightarrow\ \ l \leq min\left\{w,u,v\right\}\ \bigwedge\ max\left\{w,u,v\right\} \leq r\)
我們將每條邊轉化為二元組 \((min\left\{w,u,v\right\}\ ,\ max\left\{w,u,v\right\})\) ,於是原問題轉化為二維數點問題,用持久化線段樹維護即可。
由於詢問不強制線上,可以將詢問離線後列舉左端點用樹狀陣列維護各個右端點對應的答案,以此減少常數與程式碼量。
Code
int n,m;
vector<int>E[1000005];//在左端點存轉化後離線的邊
vector<int>Q[1000005];//在左端點存離線的詢問編號
int QR[1000005];//詢問的右端點
//以下是樹狀陣列
int T[1000005];
inline void Push(int p){
for(;p<=n;p+=(p&-p))T[p]++;
}
inline int Get(int p){
int re=0;for(;p;p-=(p&-p))re+=T[p];return re;
}
//以上是樹狀陣列
int Ans[1000005];
int main(){
Read(n);Read(m);
for(int i=1,x,y;i<n;i++){
Read(x);Read(y);
if(x>y)swap(x,y);
if(i<x)x=i;if(i>y)y=i;
E[x].push_back(y);
//邊的轉化與離線儲存
}
for(int i=1,x,y;i<=m;i++){
Read(x);Read(y);
Q[x].push_back(i);
QR[i]=y;
//詢問離線
Ans[i]=y-x+1;
//先加上|V|的貢獻
}
for(int i=n;i>=1;i--){
for(int j=0,ed=E[i].size();j<ed;j++)Push(E[i][j]);
for(int j=0,ed=Q[i].size(),p;j<ed;j++){
p=Q[i][j];Ans[p]-=Get(QR[p]);//計算|e|
}
}
for(int i=1;i<=m;i++)
cout<<Ans[i]<<'\n';
return 0;
}
本文來自部落格園,作者:蒻楊,轉載請註明原文連結:https://www.cnblogs.com/weed-yang/