有 $m$ 种花,每种花第一次选有 $a_i$ 的快乐值,之后每次有 $b_i$ 的快乐值。要选 $n$ 朵花,并最大化快乐值
直接贪心似乎没什么思路,考虑比较暴力的做法:枚举第 $i$ 种花,把所有 $a_j \ge b_i$ 的其他花先取一次,剩下全部取第 $i$ 种花。
code
code
#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 = 1e5+5; inline void fastio() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);} int a[maxn],b[maxn]; int main() { fastio(); int _,n,m; for(cin>>_;_;_--){ cin>>n>>m; ll ans = 0; vector<ll> vec,suf; rep(i,1,m){ cin>>a[i]>>b[i]; vec.pb(a[i]); } sort(ALL(vec)); per(i,m-1,0){ if(i==m-1) suf.pb(vec[i]); else suf.pb(suf.back() + vec[i]); //show1(suf.back()); } rep(i,1,m){ int pos = lower_bound(ALL(vec),b[i]) - vec.begin(); int r = m - pos; //show2(b[i],r); if(r>=n){ //show1(suf[n-1]); ans = max(ans,suf[n-1]); }else{ ll tmp = r?suf[r-1]:0; if(a[i] >= b[i]){ tmp += (ll) b[i] * (n-r); }else{ tmp += (ll)a[i] + (ll)b[i] * (n-r-1); } //show1(tmp); ans = max(ans,tmp); } } cout<<ans<<endl; } return 0; }
给一棵树,每次选 $k$ 个叶子删掉,问最多能操作多少次。
每次找儿子叶子最多的一直删即可,关键是要维护每个点的儿子叶子的个数。可以用线段树或者 $\text{set}$ 维护。
code
code
#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>