something about Educational Codeforces Round 11
2016-06-27 00:20
295 查看
这场CF的E、F两题最近才补,拿来说说。比较有意思的是,官方题解给的都不是最优复杂度。。
由于每次可以添加m种字符,所以长度每增加1,答案将乘上m,再乘上2,再减去那些重复计数的部分。
但是到底有多少重复计数了呢,可以发现,m种可添加的字符里面,有m−1种并不会改变原来的最后一个’a’的位置,于是需要减去的部分每次需要乘上m−1。这样就得到了递推方案。
E. Different Subsets For All Tuples
这道题肯定是dp,我的做法是这样的。假设你现在拥有了一个长度为i的,由m种字符(或部分)组成的串,然后在最后面添加一个字符’a’,会发生什么呢?我们令’a’具有一般性,用’x’代表除了’a’以外的字符。。比如当前串是”xxaxxxaxxx”,由于我们可以在该串的所有子序列后面选择添加或不添加这个’a’,相当于子序列个数翻倍了。但是实际上会造成一些重复,思考下发现只要减去原串中最后一个’a’之前的部分(”xxaxxx”)就好了。由于每次可以添加m种字符,所以长度每增加1,答案将乘上m,再乘上2,再减去那些重复计数的部分。
但是到底有多少重复计数了呢,可以发现,m种可添加的字符里面,有m−1种并不会改变原来的最后一个’a’的位置,于是需要减去的部分每次需要乘上m−1。这样就得到了递推方案。
#include <bits/stdc++.h> using namespace std; #define ll long long const ll mod = 1e9+7; ll dp[1000010]; int main(){ int n,m; cin>>n>>m; dp[0] = 1; ll sub = 0; for(int i=1;i<=n;i++){ dp[i] = dp[i-1] * m * 2; sub *= (m-1); if(i>1){ sub += dp[i-2]; } sub %= mod; dp[i] -= sub * m; dp[i] %= mod; } cout<<(dp + mod)%mod<<endl; return 0; }
F. Bear and Bowling 4
分治,合并的复杂度,就是计算起点和终点横跨左右两半的复杂度。对于给定的左右端点,它的答案是一个形如x+k∗y的式子,其中x和y由右端点决定,k由左端点决定。最优的合并方案是枚举左边,然后利用右边的凸壳迅速得到每个左端点对应的最优右端点。最近怎么写什么题都要凸壳= =#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 200010; const ll INF = 2e18; ll a[maxn]; ll sum[maxn]; ll incSum[maxn]; ll sufSum[maxn]; struct Point{ ll x; ll y; int id; Point(ll x,ll y,int id):x(x),y(y),id(id){ } Point(){ } bool operator<(const Point& other)const{ if(x!=other.x){ return x<other.x; } return y>other.y; } }pts[maxn]; Point ch[maxn]; int sz; ll solve(int l,int r){ if(l==r){ return a[l]; } int mid = (l+r)>>1; ll res = max(solve(l,mid),solve(mid+1,r)); int k = 1; for(int i=mid+1;i<=r;i++,k++){ pts[k].x = pts[k-1].x + a[i]; pts[k].y = pts[k-1].y + a[i] * k; pts[k].id = i; } sort(pts+1,pts+k); //Convex Hull sz = 0; for(int i=1;i<k;i++){ if(i>1 && pts[i].x == pts[i-1].x){ continue; } if(sz<2){ ch[sz++] = pts[i]; }else{ while(sz>1 && (pts[i].y-ch[sz-1].y+0.0)*(ch[sz-1].x-ch[sz-2].x) >= (ch[sz-1].y-ch[sz-2].y+0.0)*(pts[i].x-ch[sz-1].x) ){ sz--; } ch[sz++] = pts[i]; } } ll part1 = 0; int best = 0; for(int i=mid;i>=l;i--){ part1 += sufSum[mid] - sufSum[i-1]; ll C = (mid - i + 1); ll part2 = -INF; ll cur; while(best<sz){ cur = ch[best].x*C + ch[best].y; if(cur > part2){ part2 = cur; best++; }else{ break; } } best--; res = max(res,part1+part2); } return res; } int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ scanf("%I64d",&a[i]); sufSum[i] = sufSum[i-1] + a[i]; } ll ans = solve(1,n); if(ans < 0) ans = 0; cout<<ans<<endl; return 0; }
相关文章推荐
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- codeforces 618C. Constellation
- Codeforces Round #349 (Div. 2) - C
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces Round332 部分题解
- CodeForces 603A_Alternative Thinking (DP)
- CodeForces 602B_Approximating a Constant Range_DP
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)
- Codeforces #264(div 2)D.Gargari and Permutations
- Codeforces Round #236 (Div. 2)------A,B
- codeforces 257 div2 B