1. 樹中刪邊
多多有一顆 n 個節點的樹,樹中每一條邊都有一個權值。
多多還有一個長度為 n 的正整數序列:刪除樹中若干條邊之後(或者不刪),就會變成一個有 x 個連通塊的圖,
此時的得分為:剩餘邊權和 + ((兩個可以互相到達的節點屬於同一個連通塊,注意一個孤點也是一個連通塊)
多多可以刪除圖中若干條邊(可以不刪)。現在多多想知道,最多能夠得到多少分。現在請你告訴多多答案
貪心
int main() {
int n;
cin>>n;
int s = 0;
vector<int> v(n);
vector<int> a(n);
for(int i=0;i<n;i++)
cin>>v[i];
for(int i=1;i<n;i++){
int from,to;
cin>>from>>to>>a[i];
s+=a[i];
}
int res = 0;
sort(a.begin()+1,a.end());
for(int i=0;i<n;i++){
s-=a[i];
res = max(res,s+v[i]);
}
cout<<res<<endl;
return 0;
}
2. 數列操作
多多有一列正整陣列成的數列,支援兩種操作:選取一個偶數,使其值減半選取兩個數字,
移除並替換為兩個數字的和多多希望最終能夠得到一個全為奇數的數列,請計算最少需要操作幾次
思維題
int main() {
int n;
cin>>n;
vector<int> nums(n);
for(int i=0;i<n;i++)
cin>>nums[i];
int res = INT_MAX;
int odd = 0;//記錄奇數個數
//偶數透過n次減半最終可以變為奇數,也就是其第一個1在二進位制第幾位,表示要操作幾次,奇數可以將偶數變成奇數
for(auto num:nums){
int cnt = 0;
int cur = num;
while(cur%2==0){
cnt++;
cur/=2;
}
if(cnt==0) odd++;
res = min(res,cnt);
}
if(odd==0) cout<<n-1+res<<endl;
else cout<<n-odd<<endl;
}
3. 交換禮物
多多攜帶一件價值為的禮物參加了一個節日派對。除多多外在場的有個人,第i個人的當前持有的禮物價值為。
多多可以和任意當前持有禮物價值比多多低的人交換禮物。請問最少經過多少次交換,可以使得個人持有的禮物價值形成單調不減的數列
思維題
int main() {
int n,v;
cin>>n>>v;
vector<int> nums(n);
for(int i=0;i<n;i++)
cin>>nums[i];
int idx = 1;
while(idx<n){
if(nums[idx]<nums[idx-1]) break;
idx++;
}
if(idx==n){
cout<<0<<endl;
return 0;
}
nums[idx] = v;
vector<int> temp = nums;
sort(temp.begin(),temp.end());
int res = 0;
for(int i=n-1;i>=0;i--){
if(nums[i]==temp[i]) continue;
if(v==temp[i]){
res++;
v = nums[i];//替換
}
else{
cout<<-1<<endl;
return 0;
}
}
cout<<res<<endl;
return 0;
}
4. 字串操作
給定長度為n的01串,定義一次操作為, 將整個字串按順序分為兩部分, 將兩部分各自翻轉後再按原順序拼接。
提問,進行任意次的操作後,可以得到的最長的連續的01交替的子串有多長。
例:原01串為 01001,可以先將原串分為 010 和 01 兩部分, 分別翻轉得到 010 和 10 ,
按原順序拼接後得到 01010. 此時最長的連續交替子串為 01010,長度為5.
思維題
int main() {
int n;
cin>>n;
string str;
cin>>str;
int res = 1; int cnt = 1;
for(int i=1;i<2*n;i++)
if(str[i%n]!=str[(i-1)%n]){
cnt ++;
res = max(res,cnt);
}
else cnt = 1;
cout<<min(res,n)<<endl;
return 0;
}