A.直接模拟。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  6. typedef long long ll;
  7. using namespace std;
  8.  
  9. ll n,k,T,ans;
  10.  
  11. int main(){
  12. for (cin>>T; T--; ){
  13. cin>>n>>k; ans=;
  14. for (ll x=n; x; x/=k,ans++) ans+=x%k;
  15. cout<<ans-<<endl;
  16. }
  17. return ;
  18. }

B.直接模拟,用栈记录下每层的循环次数,注意当总次数超过2^31时就直接记成2^31。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<iostream>
  4. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  5. typedef long long ll;
  6. using namespace std;
  7.  
  8. const int N=;
  9. int T,top;
  10. ll x,t,s[N];
  11.  
  12. int main(){
  13. s[++top]=;
  14. for (cin>>T; T--; ){
  15. char op[]; cin>>op;
  16. if (op[]=='f') cin>>t,top++,s[top]=(s[top-]<1ll<<)?t*s[top-]:s[top-];
  17. else if (op[]=='e') top--; else x+=s[top];
  18. if (x>=1ll<<){ cout<<"OVERFLOW!!!"<<endl; return ; }
  19. }
  20. cout<<x<<endl;
  21. return ;
  22. }

C.离一个点最近的k个点一定是一个区间,枚举每个长度为k的区间即可。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  6. typedef long long ll;
  7. using namespace std;
  8.  
  9. const int N=;
  10. int n,k,T,ans,x,a[N];
  11.  
  12. int main(){
  13. for (scanf("%d",&T); T--; ){
  14. scanf("%d%d",&n,&k);
  15. rep(i,,n) scanf("%d",&a[i]);
  16. sort(a+,a+n+); ans=a[n]-a[]; x=a[];
  17. rep(i,,n-k) if ((a[i+k]-a[i]+)/<ans) ans=(a[i+k]-a[i]+)/,x=(a[i]+a[i+k]+)/;
  18. printf("%d\n",x);
  19. }
  20. return ;
  21. }

D.每设一个断点相当于将贡献加上之后所有数的和,那么将所有后缀和放在一起排序,取贡献最小的几个断点即可。注意开头是一定要设断点的。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  6. typedef long long ll;
  7. using namespace std;
  8.  
  9. const int N=;
  10. ll ans,sm[N];
  11. int n,k,s,a[N],id[N],p[N];
  12. bool cmp(int a,int b){ return sm[a]>sm[b]; }
  13.  
  14. int main(){
  15. scanf("%d%d",&n,&k);
  16. rep(i,,n) scanf("%d",&a[i]);
  17. for (int i=n; i; i--) sm[i]=sm[i+]+a[i],id[i]=i;
  18. sort(id+,id+n+,cmp);
  19. rep(i,,k) p[id[i]]=;
  20. rep(i,,n){
  21. if (p[i]) s++;
  22. ans+=1ll*s*a[i];
  23. }
  24. cout<<ans<<endl;
  25. return ;
  26. }

E.倍增记录每个区间往后选2^i个区间最多能延伸到什么位置(保证这2^i个区间首尾不断),预处理的时候先按右端点排序,再用树状数组或者二分找到与当前区间首尾相接的右端点最靠右的区间。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  6. typedef long long ll;
  7. using namespace std;
  8.  
  9. const int N=;
  10. int n,m,l,r,c[N],nxt[N][];
  11. struct P{ int l,r; }p[N];
  12. bool operator <(const P &a,const P &b){ return a.r>b.r; }
  13.  
  14. int que(int x){ int res=; for (x++; x; x-=x&-x) if (p[c[x]].r>p[res].r) res=c[x]; return res; }
  15. void add(int x,int k){ for (x++; x<=; x+=x&-x) if (p[c[x]].r<=p[k].r) c[x]=k; }
  16.  
  17. int main(){
  18. scanf("%d%d",&n,&m);
  19. rep(i,,n) scanf("%d%d",&p[i].l,&p[i].r);
  20. sort(p+,p+n+);
  21. rep(i,,n) nxt[i][]=que(p[i].r),add(p[i].l,i);
  22. rep(j,,) rep(i,,n) nxt[i][j]=nxt[nxt[i][j-]][j-];
  23. rep(i,,m){
  24. scanf("%d%d",&l,&r); int x=que(l),res=;
  25. if (x==n+){ puts("-1"); continue; }
  26. if (p[x].r>=r){ puts(""); continue; }
  27. for (int i=; ~i; i--) if (nxt[x][i] && p[nxt[x][i]].r<r) res+=<<i,x=nxt[x][i];
  28. res++; x=nxt[x][];
  29. if (p[x].r<r) puts("-1"); else printf("%d\n",res);
  30. }
  31. return ;
  32. }

F.考虑将条件转化:[l,r]值域是[1,r-l+1]等价于[l,r]区间内数两两不同且max(l,r)=r-l+1。首先我们对于每个位置i,可以轻易算出最大的r[i]使得[i,r[i]]中的数两两不同。根据max想到最值分治,然后发现每次遍历区间长度一定不大于min(mid-l,r-mid),于是就在O(nlogn)时间内解决了。

最值分治大概就是,对于当前考虑区间[l,r]找到其中最大/小的数a[mid],然后对[l,mid-1]和[mid+1,r]分别递归下去。合并时,只遍历短的那一边,计算短的那一边的每个数与长的那一边整体产生的贡献。复杂度类比启发式合并可知显然为O(nlogn)。这题中就是每次找到最大值a[mid],然后计算有多少跨过mid的合法区间,根据之前的r[i]数组可以轻松得到答案。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  4. using namespace std;
  5.  
  6. const int N=;
  7. int n,ans,a[N],b[N],lst[N],lg[N],st[N][];
  8.  
  9. int Max(int x,int y){ return a[x]>a[y] ? x : y; }
  10.  
  11. int que(int l,int r){ int t=lg[r-l+]; return Max(st[l][t],st[r-(<<t)+][t]); }
  12.  
  13. void work(int l,int r){
  14. int mid=que(l,r);
  15. rep(i,max(l,mid-a[mid]+),min(mid,r-a[mid]+)) if (b[i]>=a[mid]) ans++;
  16. if (l<mid) work(l,mid-);
  17. if (r>mid) work(mid+,r);
  18. }
  19.  
  20. int main(){
  21. scanf("%d",&n);
  22. rep(i,,n) scanf("%d",&a[i]),st[i][]=i;
  23. b[n+]=n+; rep(i,,n) lst[i]=n+;
  24. for (int i=n; i; i--) b[i]=min(b[i+]+,lst[a[i]]-i),lst[a[i]]=i;
  25. rep(i,,n) lg[i]=lg[i>>]+;
  26. rep(j,,lg[n]) rep(i,,n-(<<j)+) st[i][j]=Max(st[i][j-],st[i+(<<(j-))][j-]);
  27. work(,n); printf("%d\n",ans);
  28. return ;
  29. }

G.一个显然的DP是,f[i][j]表示前i个数分j段的最小总和,转移枚举第j段的开头,复杂度O(kn^2)。考虑对每个j做类似CDQ分治,先递归算出[l,mid]和[mid+1,r]两个区间的答案,再计算[mid+1,r]中的每个位置的最后一段开头在[l,mid]中时,能否更新答案。我们从mid开始向前向后分别求后缀和与前缀和,然后分“最后一段的最大值在[l,mid]还是[mid+1,r]”两种情况转移,发现方程是一个关于前缀后缀和的一个一次函数。于是问题变为,分治后在线往直线集中加入一条新直线,并实时查询集合中所有直线某个横坐标上的值的最大值。用单调栈维护一个上凸壳,查询时二分即可。注意一个细节是,当新加入的直线斜率和上一条直线斜率相同时,普通的计算交点方法就错了。于是复杂度为O(nklogn)。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  4. using namespace std;
  5.  
  6. const int N=,inf=1e9;
  7. int n,k,top,a[N],f[N],g[N],pre[N],suf[N];
  8. struct L{ int k,b; int F(int x){ return k*x+b; } }q[N];
  9.  
  10. bool cmp(L a,L b,L c){ return 1ll*(a.k-b.k)*(c.b-a.b)<=1ll*(a.k-c.k)*(b.b-a.b); }
  11.  
  12. void ins(L x){
  13. while (top && x.k>=q[top].k) x.b=min(x.b,q[top].b),top--;
  14. while (top> && cmp(q[top-],q[top],x)) top--;
  15. q[++top]=x;
  16. }
  17.  
  18. int calc(int x){
  19. if (!top) return inf;
  20. int l=,r=top;
  21. while (l<r){
  22. int mid=(l+r)>>;
  23. if (q[mid].F(x)<=q[mid+].F(x)) r=mid; else l=mid+;
  24. }
  25. return q[l].F(x);
  26. }
  27.  
  28. void solve(int l,int r){
  29. if (l==r) return;
  30. int mid=(l+r)>>;
  31. solve(l,mid); solve(mid+,r);
  32. suf[mid+]=; for (int i=mid; i>=l; i--) suf[i]=max(suf[i+],a[i]);
  33. pre[mid]=; rep(i,mid+,r) pre[i]=max(pre[i-],a[i]);
  34. top=;
  35. for (int i=r,j=l; i>mid; i--){
  36. while (j<=mid && suf[j+]>=pre[i]) if (g[j++]<inf) ins((L){suf[j],g[j-]-(j-)*suf[j]});
  37. f[i]=min(f[i],calc(i));
  38. }
  39. top=;
  40. for (int i=mid+,j=mid; i<=r; i++){
  41. while (j>=l && suf[j+]<=pre[i]) if (g[j--]<inf) ins((L){j+,g[j+]});
  42. f[i]=min(f[i],calc(-pre[i])+i*pre[i]);
  43. }
  44. }
  45.  
  46. int main(){
  47. scanf("%d%d",&n,&k);
  48. rep(i,,n) scanf("%d",&a[i]),pre[i]=max(pre[i-],a[i]);
  49. rep(i,,n) f[i]=pre[i]*i;
  50. rep(i,,k){
  51. rep(j,,n) g[j]=f[j],f[j]=inf;
  52. solve(,n);
  53. }
  54. printf("%d\n",f[n]);
  55. return ;
  56. }

Educational Codeforces Round 66 (Rated for Div. 2)的更多相关文章

  1. Educational Codeforces Round 66 (Rated for Div. 2) B. Catch Overflow!

    链接:https://codeforces.com/contest/1175/problem/B 题意: You are given a function ff written in some bas ...

  2. Educational Codeforces Round 66 (Rated for Div. 2) A. From Hero to Zero

    链接:https://codeforces.com/contest/1175/problem/A 题意: You are given an integer nn and an integer kk. ...

  3. Educational Codeforces Round 66 (Rated for Div. 2) A

    A. From Hero to Zero 题目链接:http://codeforces.com/contest/1175/problem/A 题目 ou are given an integer n ...

  4. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  5. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  6. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  7. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  8. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  9. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

随机推荐

  1. Generating a Random Sample from discrete probability distribution

    If is a discrete random variable taking on values , then we can write . Implementation of this formu ...

  2. 前端微信小程序电影类仿淘票票微信小程序

    需求描述及交互分析设计思路和相关知识点电影界面顶部页签切换效果设计正在热映界面布局设计即将上映界面布局设计电影详情页设计我的界面列表导航设计登录设计 相关知识点(1)swiper滑块视图容器组件,可以 ...

  3. CTF SSRF(服务器端伪造请求)

    目录 CTF SSRF(服务器端伪造请求) 一.概念 二.危害 三.漏洞挖掘与判断 四.相关函数 五.IP绕过 六.Gopher协议 1.使用限制 2.构造payload CTF SSRF(服务器端伪 ...

  4. Net core学习系列(三)——Net Core中的依赖注入

    本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...

  5. 如何SpringBoot项目改为外置Tomcat启动

    正常情况下,我们开发 SpringBoot 项目,由于内置了Tomcat,所以项目可以直接启动,部署到服务器的时候,直接打成 jar 包,就可以运行了 (使用内置 Tomcat 的话,可以在 appl ...

  6. coredump之栈溢出

    1.栈溢出引发的core往往出现出现在递归调用中. gdb时看到的特征是: 栈缺失,当前栈地址不可读. 根据栈是逆向生长的特点(栈逆向生长,所以很容易出现类似数组溢出覆盖率函数返回地址,导致函数退出地 ...

  7. 超线程技术(Hyper—Threading Technology,HTT)

    什么是超线程技术 超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算.具体讲,就是通过CPU的寄存器构成了两个逻辑处理器,来共享处理器的物理执行单元 ...

  8. python离线包下载地址

    https://pypi.org/project/pdfconv/ https://pypi.org/search/?q=major&o=

  9. 关于将汉语拼音字母“ü”改成“v”的设想和建议

    http://bbs.tianya.cn/post-free-1667253-1.shtml?_t=t -- 徐州工业职业技术学院 孙生强 <汉语拼音方案>为中国人的语言文字学习带来极大方 ...

  10. Spring MVC -- 表达式于语言(EL)

    JSP 2.0最重要的特性之一就是表达式语言(EL),JSP用户可以用它来访问应用程序数据.由于受到ECMAScript和XPath表达式语言的启发,EL也设计成可以轻松地编写免脚本(就是不用在jsp ...