话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊

T1 array:

根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好像很难搞,但是我们用exgcd求出一组特解之后的通解公式是个一次函数,通过手玩可知x,y只可能是最小正整数或最大负整数解,这就很好整,时间复杂度$O(n)$,当然也可以三分。

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=1e5+;
  5. void exgcd(int a,int b,int &x,int &y,int &gcd){//ax+by=c,gcd wei gongyueshu
  6. if(!b){
  7. gcd=a;
  8. x=;
  9. y=;
  10. }
  11. else{
  12. exgcd(b,a%b,y,x,gcd);
  13. y-=a/b*x;
  14. }
  15. }
  16. int gcd(int a,int b){
  17. return (!b)?a:gcd(b,a%b);
  18. }
  19. int solve(int a,int b,int x,int y,int k,int g){
  20. //cout<<"a=="<<a<<" b=="<<b<<" k=="<<k<<endl;
  21. int ka=a,kb=b;
  22. a/=g,b/=g;k/=g;
  23. //cout<<"a=="<<a<<" b=="<<b<<" k=="<<k<<endl;
  24. int res=0x7fffffffffffffff;
  25. int tmpx=x%b,tmpy=(k-a*tmpx)/b;
  26. res=min(res,abs(tmpx)+abs(tmpy));
  27. //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
  28. if(tmpx==){
  29. res=min(res,abs(tmpx+b)+abs(tmpy-a));
  30. res=min(res,abs(tmpx-b)+abs(tmpy+a));
  31. }
  32.  
  33. else if(tmpx<) tmpx+=b,tmpy-=a,res=min(res,abs(tmpx)+abs(tmpy));
  34. else tmpx-=b,tmpy+=a,res=min(res,abs(tmpx)+abs(tmpy));
  35. //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
  36. tmpy=y%a,tmpx=(k-b*tmpy)/a;
  37. res=min(res,abs(tmpx)+abs(tmpy));
  38. //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
  39. if(tmpy==){
  40. res=min(res,abs(tmpx+b)+abs(tmpy-a));
  41. res=min(res,abs(tmpx-b)+abs(tmpy+a));
  42. }
  43. else if(tmpy<) tmpy+=a,tmpx-=b,res=min(res,abs(tmpx)+abs(tmpy));
  44. else tmpy-=a,tmpx+=b,res=min(res,abs(tmpx)+abs(tmpy));
  45. //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
  46. return res;
  47. }
  48. int k[N];
  49. main(){
  50. //freopen("1.in","r",stdin);
  51. int n,a,b;
  52. scanf("%lld%lld%lld",&n,&a,&b);
  53. for(int i=;i<=n;++i) scanf("%lld",&k[i]);
  54. int flag=;
  55. long long ans=;
  56. int x,y;
  57. int g;
  58. exgcd(a,b,x,y,g);
  59. int tmpx=x,tmpy=y;
  60. for(int i=;i<=n;++i){
  61. //cout<<"x=="<< x<<" y=="<<y<<endl;
  62. //cout<<"gcd=="<<g<<" k[i]=="<<k[i]<<endl;
  63. if(k[i]%g!=) {flag=;break;}
  64. int tmp=k[i]/g;
  65. x=tmpx*tmp,y=tmpy*tmp;
  66. //cout<<"x=="<<x<<" y=="<<y<<endl;
  67. int res=solve(a,b,x,y,k[i],g);
  68. //cout<<"res=="<<res<<endl;
  69. ans+=res;
  70. }
  71. if(flag) puts("-1");
  72. else printf("%lld\n",ans);
  73. return ;
  74. }

array

T2 pair

考场上一看到这题发现和队长快跑那题很像,然后就回忆起了那天调了一个下午影魔的一个log在线做法然后水果那道题的惨痛经历,果然水题没有好下场啊qwq

首先设出dp定义$dp_{i,s}$表示到i并且选i,$max(a_i)=j$的最大值。

我们在来考虑他给出的限制,如果$a_i < b_j$且 $a_j>b_i$ 那么一定是i在j前。反之同理。

那么我们可以按$max(a,b)$排序,然后dp

转移时,我们要分类讨论

如果$a_i < b_i$,因为要$max(a)<b_i$所以,$f[i-1][a[i]]$到$f[i-1][b[i]]$的最大值不会改变,直接加$val$就好,在$1-a[i-1]$的最大值变为了$a[i]$,用前面的最大值更新dp就好了。

如果$a_i > b_i$,因为要$max(a)<b_i$所以,$1-b[i]$的最大值变为$a[i]$,同上更新即可。

以上操作只需要维护一棵资磁区间加,单点修改,区间max线段树就好了。

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=2e5+;
  5. int cnt,lsh[N<<];
  6. struct node{
  7. int a,b,w;
  8. }p[N];
  9. int dp[N];
  10. bool cmp(node x,node y)
  11. {
  12. if(max(x.b,x.a)!=max(y.b,y.a))
  13. return max(x.b,x.a)<max(y.b,y.a);
  14. else return x.b<y.b;
  15. }
  16. struct SegmentTree{
  17. int l,r,mx,lazy;
  18. }tr[N<<];
  19. void build(int p,int l,int r){
  20. tr[p].l=l,tr[p].r=r;
  21. if(l==r){return ;}
  22. int mid=(l+r)>>;
  23. build(p<<,l,mid);
  24. build(p<<|,mid+,r);
  25. }
  26. void down(int p){
  27. if(!tr[p].lazy) return ;
  28. tr[p<<].lazy+=tr[p].lazy,tr[p<<|].lazy+=tr[p].lazy;
  29. tr[p<<].mx+=tr[p].lazy,tr[p<<|].mx+=tr[p].lazy;
  30. tr[p].lazy=;
  31. }
  32. void add(int p,int l,int r,int ll,int rr,int val){
  33. if(ll<=l&&r<=rr){
  34. tr[p].mx+=val;
  35. tr[p].lazy+=val;
  36. return ;
  37. }
  38. down(p);
  39. int mid=(tr[p].l+tr[p].r)>>;
  40. if(ll<=mid) add(p<<,l,mid,ll,rr,val);
  41. if(rr>mid) add(p<<|,mid+,r,ll,rr,val);
  42. tr[p].mx=max(tr[p<<].mx,tr[p<<|].mx);
  43. }
  44. int q_mx=;
  45. void ask(int p,int l,int r,int ll,int rr){
  46. if(ll<=l&&r<=rr){
  47. q_mx=max(q_mx,tr[p].mx);
  48. return ;
  49. }
  50. down(p);
  51. int mid=(tr[p].l+tr[p].r)>>;
  52. if(ll<=mid) ask(p<<,l,mid,ll,rr);
  53. if(rr>mid) ask(p<<|,mid+,r,ll,rr);
  54. }
  55. void update(int p,int l,int r,int pos,int val){
  56. if(l==r){
  57. tr[p].mx=max(val,tr[p].mx);
  58. return ;
  59. }
  60. down(p);
  61. int mid=(tr[p].l+tr[p].r)>>;
  62. if(pos<=mid) update(p<<,l,mid,pos,val);
  63. else update(p<<|,mid+,r,pos,val);
  64. tr[p].mx=max(tr[p<<].mx,tr[p<<|].mx);
  65. }
  66. signed main(){
  67. // freopen("2.in","r",stdin);
  68. int n;
  69. scanf("%lld",&n);
  70. for(int i=;i<=n;++i){
  71. scanf("%lld%lld%lld",&p[i].a,&p[i].b,&p[i].w);
  72. }
  73. sort(p+,p+n+,cmp);
  74. for(int i=;i<=n;++i) lsh[++cnt]=p[i].a,lsh[++cnt]=p[i].b;
  75. sort(lsh+,lsh+cnt+);
  76. int len=unique(lsh+,lsh+cnt+)-(lsh+);
  77. int maxn=;
  78. for(int i=;i<=n;++i){
  79. p[i].a=lower_bound(lsh+,lsh+len+,p[i].a)-lsh;
  80. p[i].b=lower_bound(lsh+,lsh+len+,p[i].b)-lsh;
  81. maxn=max(maxn,p[i].a);
  82. maxn=max(maxn,p[i].b);
  83. }
  84. build(,,maxn);
  85. // cout<<"maxn=="<<maxn<<endl;
  86. for(int i=;i<=n;++i){
  87. if(p[i].a>p[i].b){
  88. q_mx=;
  89. ask(,,maxn,,p[i].b);
  90. // cout<<q_mx<<endl;
  91. dp[i]=max(dp[i],q_mx+p[i].w);
  92. }
  93. else{
  94. q_mx=;
  95. ask(,,maxn,,p[i].a);
  96. // cout<<q_mx<<endl;
  97. dp[i]=max(dp[i],q_mx+p[i].w);
  98. add(,,maxn,p[i].a,p[i].b,p[i].w);
  99. }
  100. update(,,maxn,p[i].a,dp[i]);
  101. }
  102. printf("%lld\n",tr[].mx);
  103. }

pair

T3 distance

感觉思路和meet in the middle 有些相似,不过也不太一样废话,这提重点思路就在于相当于从中间把两条路径连起来。

具体做法就是以所有特殊点为源点,跑一个多源点spfa,然后记录每个点,离最特殊点的距离,以及是那一个特殊点。跑完spfa后枚举所有边,如果两个端点不同就更新这两个端点的最近特殊点的答案。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. const int N=2e5+;
  5. int to[N<<],nex[N<<],edge[N<<],fr[N<<];
  6. int first[N];
  7. bool is[N];
  8. int sp[N],dis[N],v[N],ans[N];
  9. int tot;
  10. void add(int a,int b,int c){
  11. to[++tot]=b,nex[tot]=first[a],first[a]=tot,edge[tot]=c,fr[tot]=a;
  12. }
  13. int sour[N];
  14. int n,m,p;
  15. void spfa(){
  16. for(int i=;i<=n;++i) dis[i]=;
  17. queue<int> q;
  18. for(int i=;i<=p;++i) q.push(sp[i]),dis[sp[i]]=,v[sp[i]]=,sour[sp[i]]=sp[i];
  19. while(q.size()){
  20. int x=q.front();q.pop();
  21. v[x]=;
  22. for(int i=first[x];i;i=nex[i]){
  23. int y=to[i],z=edge[i];
  24. if(dis[y]>dis[x]+z){
  25. dis[y]=dis[x]+z;
  26. sour[y]=sour[x];
  27. if(!v[y]) q.push(y),v[y]=;
  28. }
  29. }
  30. }
  31. }
  32. signed main(){
  33. //freopen("3.in","r",stdin);
  34. scanf("%lld%lld%lld",&n,&m,&p);
  35. for(int i=;i<=n;++i) ans[i]=;
  36. for(int i=;i<=p;++i) {scanf("%lld",&sp[i]);is[sp[i]]=;}
  37. for(int i=;i<=m;++i){
  38. int x,y,w;
  39. scanf("%lld%lld%lld",&x,&y,&w);
  40. add(x,y,w);
  41. add(y,x,w);
  42. }
  43. spfa();
  44. // for(int i=1;i<=n;++i) cout<<"sour["<<i<<"]=="<<sour[i]<<" dis["<<i<<"]=="<<dis[i]<<endl;
  45. for(int i=;i<=tot;i+=){
  46. if(sour[fr[i]]!=sour[to[i]]){
  47. // cout<<"g"<<fr[i]<<" "<<to[i]<<" "<<edge[i]<<endl;
  48. ans[sour[fr[i]]]=min(ans[sour[fr[i]]],dis[fr[i]]+dis[to[i]]+edge[i]);
  49. ans[sour[to[i]]]=min(ans[sour[to[i]]],dis[fr[i]]+dis[to[i]]+edge[i]);
  50.  
  51. }
  52. }
  53. for(int i=;i<=p;++i) printf("%lld ",ans[sp[i]]);
  54. }
  55. /*
  56. 5 6 3
  57. 2 4 5
  58. 1 2 4
  59. 1 3 1
  60. 1 4 1
  61. 1 5 4
  62. 2 3 1
  63. 3 4 3
  64. */

distance

CSP-S 模拟测试92 题解的更多相关文章

  1. [CSP-S模拟测试92]题解

    A.数列 显然每个数的答案是互相独立的,直接扩欧求解.我们需要最小化$ax+by=gcd(a,b)$中的$|x|+|y|$,而显然当x或y靠近0时答案可能最优,列个不等式求一下即可. 能$O(1)$千 ...

  2. csp-s模拟测试92

    csp-s模拟测试92 关于$T1$:最短路这一定建边最短路. 关于$T2$:傻逼$Dp$这一定线段树优化$Dp$. 关于$T3$:最小生成树+树P+换跟一定是这样. 深入(?)思考$T1$:我是傻逼 ...

  3. [考试反思]1029csp-s模拟测试92:弱智

    我只能这么评价我自己. 看这个提交时间...我没话可说... T1半个世界都A了还是切不掉.又一次挂细节. T2不会证明的乱搞(虽然可以证明)A了没什么可说的算是水过. T3之前水过的题(打的次正解) ...

  4. CSP-S 模拟测试94题解

    T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...

  5. CSP-S模拟测试 88 题解

    T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...

  6. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

  7. CSP-S 模拟测试 51 题解

    考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...

  8. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  9. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

随机推荐

  1. javascript 写一个ajax 自动拦截,并下载数据

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  2. vue.js入门语法

    1.入门 <div id="vue_det"> <h1>site : {{site}}</h1> //两个大括号显示参数 <h1>u ...

  3. MarkDown 语法大全查询

    目录 1. 斜体和粗体 2. 分级标题 3. 超链接 3.1. 行内式 3.2. 参考式 3.3. 自动链接 4. 锚点 5. 列表 5.1. 无序列表 5.2. 有序列表 5.3. 定义型列表 5. ...

  4. 前端开发 Vue -0前言

    Vue2.0 新手完全填坑攻略——从环境搭建到发布 Vue2 入门,读这篇就够了 Jinkey原创感谢 showonne.yubang 技术指导Demo 地址:http://demo.jinkey.i ...

  5. Django rest-framework框架-组件之渲染器

    渲染器: from rest_framework.renderers import BrowsableAPIRenderer,AdminRenderer,HTMLFormRenderer,JSONRe ...

  6. CPCT精细化运营:客户、产品、渠道、时机

    关键词:CPCT.精细化运营思维.客户.产品.渠道.时机.运营 电信运营商市场饱和,用户新增主要靠弃卡后重新入网以及异网用户策反. 用户新增已如此艰难,所以更加关注存量用户经营. 运营商营销资源不断收 ...

  7. 关于Vue中,checkBox等组件在赋值后,点击切换页面未及时更新问题

    我们经常碰到这样的问题,在v-for循环中,给某些组件(此处以checkBox为例)赋值后,组件并不能正常切换, 这是因为数据层太多,render函数没有自动更新,需手动强制刷新. 解决方法:在切换c ...

  8. nodejs入门API之fs模块

    fs模块下的类与FS常量 fs模块下的主要方法 fs的Promise API与FileHandle类 一.fs模块下的类 1.1 fs.Dir:表示目录流的类,由 fs.opendir().fs.op ...

  9. iOS分类(category),类扩展(extension)—史上最全攻略

    背景: 在大型项目,企业级开发中多人同时维护同一个类,此时程序员A因为某项需求只想给当前类currentClass添加一个方法newMethod,那该怎么办呢? 最简单粗暴的方式是把newMethod ...

  10. ASE19团队项目 beta阶段 model组 scrum2 记录

    本次会议于12月3日,19时整在微软北京西二号楼sky garden召开,持续10分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...