【LittleXi】拼多多后端8.11解题报告
极限ak,开题顺序3421成谜
A、旅行计划
题意:
给定n个旅行计划,每个旅行计划完成的时间只能是xi,xi+d,xi+2d,...,并且每天最多只能完成一个旅游,求最小时间
题解:
可以考虑维护当前的天数result
如果result小于当前旅行计划开始的天数,那么result = day_i
否则求最小的b使得day_i + b * d > result
注意坑就是求b的时候,也可以day_i + b * d = result , 此时要b++
// 1 #include<bits/stdc++.h> using namespace std; #define ll long long void solve(){ ll n; cin>>n; vector<vector<ll>> data(n,vector<ll>(3)); for(ll i= 0;i<n;i++){ cin>>data[i][0]>>data[i][1]>>data[i][2]; } sort(data.begin(),data.end()); ll result = 1; for(ll i =0;i<n;i++){ vector<ll> current = data[i]; if(result < current[1]){ result = current[1]; } else{ ll day = current[1]; ll dis = result - day; ll b = dis/current[2] + (dis%current[2] > 0); if(day + b * current[2]==result) b ++; result = day + b * current[2]; } } cout<<result<<endl; } signed main(){ cin.tie(0);cout.tie(0); ios::sync_with_stdio(0); solve(); }
B、多多的作业
题意:
给定n个作业,作业有开始时间和需要的时间,求最小总作业消耗时间,单个作业消耗时间是作业完成时间减去作业开始时间
题解:
可以考虑使用优先队列进行贪心, 每次获取作业的时候,对于前面那个时间片,我们优先让消耗时间小的作业被计算
代码:
// 2 #include<bits/stdc++.h> using namespace std; #define ll long long void solve(){ ll n; cin>>n; vector<pair<ll,ll>> vp(n); for(ll i =0;i<n;i++) cin>>vp[i].first>>vp[i].second; priority_queue<ll,vector<ll>,greater<ll>> pq; ll t = 1 , ans = 0; pq.push(vp[0].second); for(ll i =1;i<n;i++){ ll d = vp[i].first - vp[i-1].first; while(pq.size()&&d){ auto x = pq.top();pq.pop(); ll dis = min(x,d); ans += dis * (pq.size() + 1); x -= dis ; d -= dis; if(x) pq.push(x); } pq.push(vp[i].second); } while(pq.size()){ ll x = pq.top();pq.pop(); ans += x * (pq.size() + 1); } cout<<ans; } signed main(){ cin.tie(0);cout.tie(0); ios::sync_with_stdio(0); solve(); }
C、玫瑰和牡丹
题意:
给一个01串,你可以最多选择一个区间进行反转,0->1 , 1->0 ,求最终abs(cnt[0]-cnt[1])的可能数
题解:
我们可以这样考虑,每次延长我们的[l,r]区间一次,cnt[0] - cnt[1] 要么+1,要么-1,所以我们可以求一个区间,使得cnt[0] - cnt[1] 最大或者最小,这个可以使用前缀和解决,那么对于最大的cnt[0] - cnt[1] , 一定可以每次+2到达,所以沿途的数字都可以到达
代码:
// 3 #include<bits/stdc++.h> using namespace std; #define ll long long void solve(){ int n ;cin>>n; vector<int> a(n); for(int&x:a) cin>>x; for(int&x:a) if(x==0) x = -1; int prmi = 0 , prmx = 0; int pr = 0; int mx = 0 , mi = 0; for(int i = 0;i<n;i++){ pr += a[i]; mx = max(mx,pr-prmi); mi = min(mi,pr-prmx); prmx = max(prmx,pr); prmi = min(prmi,pr); } set<int> se; int sm = accumulate(a.begin(),a.end(),0); for(int i = sm - 2*mx ; i <= sm -2*mi;i+=2){ se.insert(abs(i)); } cout<<se.size(); } signed main(){ cin.tie(0);cout.tie(0); ios::sync_with_stdio(0); solve(); }
D、哈希表
难度:区域赛铜牌题目,一股ACM味儿
题意:
哈希函数为f = x % n , 给定一个插入完成的哈希表,要求还原插入顺序,如果多个可能,还原字典序最小的
题解:
很容易想到使用拓扑排序,对于从i位置跳到j位置的数字, 将[i,j-1]的所有点连向j,然后进行拓扑排序+贪心就行,时间复杂度n^2 , 不行
可以考虑优化,删除一个数字之后,一定是右边最靠近这个数字可能被选,可以压进优先队列中,查找右边那个数字可以考虑使用树状数组+二分,时间复杂度nlg^2n
代码:
// 4 #include<bits/stdc++.h> using namespace std; #define ll long long //坐标从0开始直接用的树状数组 template <typename T> class Fenwick { private: int n; vector<T> c; int lowbits(int x){ return (-x) & x; } int pre_sum(int i){ int re = 0; for (; i > 0; i -= lowbits(i)) re += c[i]; return re; } public: explicit Fenwick<T>(vector<T> v){ this->n = v.size(); this->c = vector<T>(n+1,0); for(int i=0;i<n;i++) add(i,v[i]); }; void add(int i, int val){ ++i; for (;i<=n; i += lowbits(i)) c[i] += val; } int range_sum(int i,int j){ ++i;++j; return pre_sum(j) - pre_sum(i - 1); } }; void solve(){ int n;cin>>n; vector<int> a(n); for(int &x:a) cin>>x; priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq; map<int,int> mp; for(int i =0;i<n;i++){ if(a[i]==-1) a[i] = 0; else if(a[i]%n==i){ pq.push({a[i],i}); mp[a[i]] = 1; } } for(int i =0 ;i < n;i++) a.push_back(a[i]); vector<int> b = a; for(int&x:b) if(x) x = 1; Fenwick<int> fw(b); vector<int> ans; while(pq.size()){ auto p = pq.top();pq.pop(); int x = p.first , pos = p.second; ans.push_back(x); fw.add(pos,-1);fw.add(pos+n,-1); int l = pos , r = 2*n; while(l+1!=r){ int m = l+r>>1; if(fw.range_sum(pos,m)==0) l = m; else r = m; } l++; if(l<2*n&&fw.range_sum(pos,l)==1){ if(mp[a[l]]) continue; int lp = a[l]%n; if(lp > l) l+=n; if(fw.range_sum(lp, l - 1)==0){ mp[a[l]] = 1; if(l >= n ) l -= n; pq.push({a[l],l}); } } } for(int x:ans) cout<<x<<" "; } signed main(){ cin.tie(0);cout.tie(0); ios::sync_with_stdio(0); solve(); }
❤关注LittleXi ,谢谢喵, ACM金牌,持续更新更多题解❤
也可以提供大厂算法辅导喵