这里会显示出您选择的修订版和当前版本之间的差别。
| 后一修订版 | 前一修订版 | ||
|
2020-2021:teams:wangzai_milk:cf贪心练习 [2020/08/07 12:59] wzx27 创建 |
2020-2021:teams:wangzai_milk:cf贪心练习 [2020/08/07 13:03] (当前版本) wzx27 |
||
|---|---|---|---|
| 行 69: | 行 69: | ||
| } | } | ||
| </code> </hidden> | </code> </hidden> | ||
| + | \\ | ||
| + | |||
| + | ==== CF1385F ==== | ||
| + | |||
| + | 给一棵树,每次选 $k$ 个叶子删掉,问最多能操作多少次。 | ||
| + | |||
| + | 每次找儿子叶子最多的一直删即可,关键是要维护每个点的儿子叶子的个数。可以用线段树或者 $\text{set}$ 维护。 | ||
| + | |||
| + | <hidden code> <code cpp> | ||
| + | #include<bits/stdc++.h> | ||
| + | #define ALL(x) (x).begin(),(x).end() | ||
| + | #define ll long long | ||
| + | #define db double | ||
| + | #define ull unsigned long long | ||
| + | #define pii_ pair<int,int> | ||
| + | #define mp_ make_pair | ||
| + | #define pb push_back | ||
| + | #define fi first | ||
| + | #define se second | ||
| + | #define rep(i,a,b) for(int i=(a);i<=(b);i++) | ||
| + | #define per(i,a,b) for(int i=(a);i>=(b);i--) | ||
| + | #define show1(a) cout<<#a<<" = "<<a<<endl | ||
| + | #define show2(a,b) cout<<#a<<" = "<<a<<"; "<<#b<<" = "<<b<<endl | ||
| + | using namespace std; | ||
| + | const ll INF = 1LL<<60; | ||
| + | const int inf = 1<<30; | ||
| + | const int maxn = 2e5+5; | ||
| + | inline void fastio() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);} | ||
| + | int cnt[maxn],n,k; | ||
| + | vector<int> g[maxn]; | ||
| + | set<int> sg[maxn]; | ||
| + | struct node | ||
| + | { | ||
| + | int id,num; | ||
| + | bool operator < (const node e) const | ||
| + | { | ||
| + | if(num != e.num) return num < e.num; | ||
| + | return id < e.id; | ||
| + | } | ||
| + | }tr[maxn<<2]; | ||
| + | void dfs(int u,int f) | ||
| + | { | ||
| + | cnt[u] = 0; | ||
| + | for(int v:g[u])if(v!=f){ | ||
| + | dfs(v,u); | ||
| + | if(g[v].size()==1) cnt[u]++; | ||
| + | } | ||
| + | } | ||
| + | void push_up(int id) | ||
| + | { | ||
| + | tr[id] = max(tr[id<<1],tr[id<<1|1]); | ||
| + | } | ||
| + | void build(int id,int l,int r) | ||
| + | { | ||
| + | if(l==r){ | ||
| + | tr[id] = (node){l,cnt[l]}; | ||
| + | return ; | ||
| + | } | ||
| + | int mid = (l+r)>>1; | ||
| + | build(id<<1,l,mid);build(id<<1|1,mid+1,r); | ||
| + | push_up(id); | ||
| + | } | ||
| + | void update(int id,int stl,int str,int pos,int flag) | ||
| + | { | ||
| + | if(stl==str){ | ||
| + | if(!flag) tr[id].num %= k; | ||
| + | else tr[id].num++; | ||
| + | return ; | ||
| + | } | ||
| + | int mid = (stl+str)>>1; | ||
| + | if(pos<=mid) update(id<<1,stl,mid,pos,flag); | ||
| + | else update(id<<1|1,mid+1,str,pos,flag); | ||
| + | push_up(id); | ||
| + | } | ||
| + | int main() | ||
| + | { | ||
| + | fastio(); | ||
| + | int _; | ||
| + | for(cin>>_;_;_--){ | ||
| + | cin>>n>>k; | ||
| + | rep(i,1,n) g[i].clear(),sg[i].clear(); | ||
| + | rep(i,1,n-1){ int u,v; | ||
| + | cin>>u>>v; | ||
| + | g[u].pb(v); | ||
| + | g[v].pb(u); | ||
| + | } | ||
| + | if(k==1){ | ||
| + | cout<<n-1<<endl;continue; | ||
| + | } | ||
| + | rep(i,1,n){ | ||
| + | if(g[i].size()!=1) {dfs(i,0);break;} | ||
| + | } | ||
| + | rep(u,1,n){ | ||
| + | for(int v:g[u]) if(g[v].size() > 1) sg[u].insert(v); | ||
| + | } | ||
| + | build(1,1,n); | ||
| + | int ans = 0; | ||
| + | while(1){ | ||
| + | node tmp = tr[1]; | ||
| + | if(tmp.num < k) break; | ||
| + | int num = tmp.num / k; | ||
| + | ans += num; | ||
| + | update(1,1,n,tmp.id,0); | ||
| + | cnt[tmp.id] -= num*k; | ||
| + | if(cnt[tmp.id]==0 && sg[tmp.id].size()==1){ | ||
| + | int f = *sg[tmp.id].begin(); | ||
| + | sg[f].erase(sg[f].find(tmp.id)); | ||
| + | cnt[f]++; | ||
| + | update(1,1,n,f,1); | ||
| + | } | ||
| + | } | ||
| + | cout<<ans<<endl; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </hidden> </code> | ||