CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊
T1 array:
根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好像很难搞,但是我们用exgcd求出一组特解之后的通解公式是个一次函数,通过手玩可知x,y只可能是最小正整数或最大负整数解,这就很好整,时间复杂度$O(n)$,当然也可以三分。
- #include<bits/stdc++.h>
- #define int long long
- using namespace std;
- const int N=1e5+;
- void exgcd(int a,int b,int &x,int &y,int &gcd){//ax+by=c,gcd wei gongyueshu
- if(!b){
- gcd=a;
- x=;
- y=;
- }
- else{
- exgcd(b,a%b,y,x,gcd);
- y-=a/b*x;
- }
- }
- int gcd(int a,int b){
- return (!b)?a:gcd(b,a%b);
- }
- int solve(int a,int b,int x,int y,int k,int g){
- //cout<<"a=="<<a<<" b=="<<b<<" k=="<<k<<endl;
- int ka=a,kb=b;
- a/=g,b/=g;k/=g;
- //cout<<"a=="<<a<<" b=="<<b<<" k=="<<k<<endl;
- int res=0x7fffffffffffffff;
- int tmpx=x%b,tmpy=(k-a*tmpx)/b;
- res=min(res,abs(tmpx)+abs(tmpy));
- //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
- if(tmpx==){
- res=min(res,abs(tmpx+b)+abs(tmpy-a));
- res=min(res,abs(tmpx-b)+abs(tmpy+a));
- }
- else if(tmpx<) tmpx+=b,tmpy-=a,res=min(res,abs(tmpx)+abs(tmpy));
- else tmpx-=b,tmpy+=a,res=min(res,abs(tmpx)+abs(tmpy));
- //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
- tmpy=y%a,tmpx=(k-b*tmpy)/a;
- res=min(res,abs(tmpx)+abs(tmpy));
- //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
- if(tmpy==){
- res=min(res,abs(tmpx+b)+abs(tmpy-a));
- res=min(res,abs(tmpx-b)+abs(tmpy+a));
- }
- else if(tmpy<) tmpy+=a,tmpx-=b,res=min(res,abs(tmpx)+abs(tmpy));
- else tmpy-=a,tmpx+=b,res=min(res,abs(tmpx)+abs(tmpy));
- //cout<<"tmpx=="<<tmpx<<" tmpy=="<<tmpy<<" res=="<<res<<endl;
- return res;
- }
- int k[N];
- main(){
- //freopen("1.in","r",stdin);
- int n,a,b;
- scanf("%lld%lld%lld",&n,&a,&b);
- for(int i=;i<=n;++i) scanf("%lld",&k[i]);
- int flag=;
- long long ans=;
- int x,y;
- int g;
- exgcd(a,b,x,y,g);
- int tmpx=x,tmpy=y;
- for(int i=;i<=n;++i){
- //cout<<"x=="<< x<<" y=="<<y<<endl;
- //cout<<"gcd=="<<g<<" k[i]=="<<k[i]<<endl;
- if(k[i]%g!=) {flag=;break;}
- int tmp=k[i]/g;
- x=tmpx*tmp,y=tmpy*tmp;
- //cout<<"x=="<<x<<" y=="<<y<<endl;
- int res=solve(a,b,x,y,k[i],g);
- //cout<<"res=="<<res<<endl;
- ans+=res;
- }
- if(flag) puts("-1");
- else printf("%lld\n",ans);
- return ;
- }
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线段树就好了。
- #include<bits/stdc++.h>
- #define int long long
- using namespace std;
- const int N=2e5+;
- int cnt,lsh[N<<];
- struct node{
- int a,b,w;
- }p[N];
- int dp[N];
- bool cmp(node x,node y)
- {
- if(max(x.b,x.a)!=max(y.b,y.a))
- return max(x.b,x.a)<max(y.b,y.a);
- else return x.b<y.b;
- }
- struct SegmentTree{
- int l,r,mx,lazy;
- }tr[N<<];
- void build(int p,int l,int r){
- tr[p].l=l,tr[p].r=r;
- if(l==r){return ;}
- int mid=(l+r)>>;
- build(p<<,l,mid);
- build(p<<|,mid+,r);
- }
- void down(int p){
- if(!tr[p].lazy) return ;
- tr[p<<].lazy+=tr[p].lazy,tr[p<<|].lazy+=tr[p].lazy;
- tr[p<<].mx+=tr[p].lazy,tr[p<<|].mx+=tr[p].lazy;
- tr[p].lazy=;
- }
- void add(int p,int l,int r,int ll,int rr,int val){
- if(ll<=l&&r<=rr){
- tr[p].mx+=val;
- tr[p].lazy+=val;
- return ;
- }
- down(p);
- int mid=(tr[p].l+tr[p].r)>>;
- if(ll<=mid) add(p<<,l,mid,ll,rr,val);
- if(rr>mid) add(p<<|,mid+,r,ll,rr,val);
- tr[p].mx=max(tr[p<<].mx,tr[p<<|].mx);
- }
- int q_mx=;
- void ask(int p,int l,int r,int ll,int rr){
- if(ll<=l&&r<=rr){
- q_mx=max(q_mx,tr[p].mx);
- return ;
- }
- down(p);
- int mid=(tr[p].l+tr[p].r)>>;
- if(ll<=mid) ask(p<<,l,mid,ll,rr);
- if(rr>mid) ask(p<<|,mid+,r,ll,rr);
- }
- void update(int p,int l,int r,int pos,int val){
- if(l==r){
- tr[p].mx=max(val,tr[p].mx);
- return ;
- }
- down(p);
- int mid=(tr[p].l+tr[p].r)>>;
- if(pos<=mid) update(p<<,l,mid,pos,val);
- else update(p<<|,mid+,r,pos,val);
- tr[p].mx=max(tr[p<<].mx,tr[p<<|].mx);
- }
- signed main(){
- // freopen("2.in","r",stdin);
- int n;
- scanf("%lld",&n);
- for(int i=;i<=n;++i){
- scanf("%lld%lld%lld",&p[i].a,&p[i].b,&p[i].w);
- }
- sort(p+,p+n+,cmp);
- for(int i=;i<=n;++i) lsh[++cnt]=p[i].a,lsh[++cnt]=p[i].b;
- sort(lsh+,lsh+cnt+);
- int len=unique(lsh+,lsh+cnt+)-(lsh+);
- int maxn=;
- for(int i=;i<=n;++i){
- p[i].a=lower_bound(lsh+,lsh+len+,p[i].a)-lsh;
- p[i].b=lower_bound(lsh+,lsh+len+,p[i].b)-lsh;
- maxn=max(maxn,p[i].a);
- maxn=max(maxn,p[i].b);
- }
- build(,,maxn);
- // cout<<"maxn=="<<maxn<<endl;
- for(int i=;i<=n;++i){
- if(p[i].a>p[i].b){
- q_mx=;
- ask(,,maxn,,p[i].b);
- // cout<<q_mx<<endl;
- dp[i]=max(dp[i],q_mx+p[i].w);
- }
- else{
- q_mx=;
- ask(,,maxn,,p[i].a);
- // cout<<q_mx<<endl;
- dp[i]=max(dp[i],q_mx+p[i].w);
- add(,,maxn,p[i].a,p[i].b,p[i].w);
- }
- update(,,maxn,p[i].a,dp[i]);
- }
- printf("%lld\n",tr[].mx);
- }
pair
T3 distance
感觉思路和meet in the middle 有些相似,不过也不太一样废话,这提重点思路就在于相当于从中间把两条路径连起来。
具体做法就是以所有特殊点为源点,跑一个多源点spfa,然后记录每个点,离最特殊点的距离,以及是那一个特殊点。跑完spfa后枚举所有边,如果两个端点不同就更新这两个端点的最近特殊点的答案。
- #include<bits/stdc++.h>
- using namespace std;
- #define int long long
- const int N=2e5+;
- int to[N<<],nex[N<<],edge[N<<],fr[N<<];
- int first[N];
- bool is[N];
- int sp[N],dis[N],v[N],ans[N];
- int tot;
- void add(int a,int b,int c){
- to[++tot]=b,nex[tot]=first[a],first[a]=tot,edge[tot]=c,fr[tot]=a;
- }
- int sour[N];
- int n,m,p;
- void spfa(){
- for(int i=;i<=n;++i) dis[i]=;
- queue<int> q;
- for(int i=;i<=p;++i) q.push(sp[i]),dis[sp[i]]=,v[sp[i]]=,sour[sp[i]]=sp[i];
- while(q.size()){
- int x=q.front();q.pop();
- v[x]=;
- for(int i=first[x];i;i=nex[i]){
- int y=to[i],z=edge[i];
- if(dis[y]>dis[x]+z){
- dis[y]=dis[x]+z;
- sour[y]=sour[x];
- if(!v[y]) q.push(y),v[y]=;
- }
- }
- }
- }
- signed main(){
- //freopen("3.in","r",stdin);
- scanf("%lld%lld%lld",&n,&m,&p);
- for(int i=;i<=n;++i) ans[i]=;
- for(int i=;i<=p;++i) {scanf("%lld",&sp[i]);is[sp[i]]=;}
- for(int i=;i<=m;++i){
- int x,y,w;
- scanf("%lld%lld%lld",&x,&y,&w);
- add(x,y,w);
- add(y,x,w);
- }
- spfa();
- // for(int i=1;i<=n;++i) cout<<"sour["<<i<<"]=="<<sour[i]<<" dis["<<i<<"]=="<<dis[i]<<endl;
- for(int i=;i<=tot;i+=){
- if(sour[fr[i]]!=sour[to[i]]){
- // cout<<"g"<<fr[i]<<" "<<to[i]<<" "<<edge[i]<<endl;
- ans[sour[fr[i]]]=min(ans[sour[fr[i]]],dis[fr[i]]+dis[to[i]]+edge[i]);
- ans[sour[to[i]]]=min(ans[sour[to[i]]],dis[fr[i]]+dis[to[i]]+edge[i]);
- }
- }
- for(int i=;i<=p;++i) printf("%lld ",ans[sp[i]]);
- }
- /*
- 5 6 3
- 2 4 5
- 1 2 4
- 1 3 1
- 1 4 1
- 1 5 4
- 2 3 1
- 3 4 3
- */
distance
CSP-S 模拟测试92 题解的更多相关文章
- [CSP-S模拟测试92]题解
A.数列 显然每个数的答案是互相独立的,直接扩欧求解.我们需要最小化$ax+by=gcd(a,b)$中的$|x|+|y|$,而显然当x或y靠近0时答案可能最优,列个不等式求一下即可. 能$O(1)$千 ...
- csp-s模拟测试92
csp-s模拟测试92 关于$T1$:最短路这一定建边最短路. 关于$T2$:傻逼$Dp$这一定线段树优化$Dp$. 关于$T3$:最小生成树+树P+换跟一定是这样. 深入(?)思考$T1$:我是傻逼 ...
- [考试反思]1029csp-s模拟测试92:弱智
我只能这么评价我自己. 看这个提交时间...我没话可说... T1半个世界都A了还是切不掉.又一次挂细节. T2不会证明的乱搞(虽然可以证明)A了没什么可说的算是水过. T3之前水过的题(打的次正解) ...
- CSP-S 模拟测试94题解
T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...
- CSP-S模拟测试 88 题解
T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...
- CSP-S 模拟测试57题解
人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...
- CSP-S 模拟测试 51 题解
考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
随机推荐
- javascript 写一个ajax 自动拦截,并下载数据
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...
- vue.js入门语法
1.入门 <div id="vue_det"> <h1>site : {{site}}</h1> //两个大括号显示参数 <h1>u ...
- MarkDown 语法大全查询
目录 1. 斜体和粗体 2. 分级标题 3. 超链接 3.1. 行内式 3.2. 参考式 3.3. 自动链接 4. 锚点 5. 列表 5.1. 无序列表 5.2. 有序列表 5.3. 定义型列表 5. ...
- 前端开发 Vue -0前言
Vue2.0 新手完全填坑攻略——从环境搭建到发布 Vue2 入门,读这篇就够了 Jinkey原创感谢 showonne.yubang 技术指导Demo 地址:http://demo.jinkey.i ...
- Django rest-framework框架-组件之渲染器
渲染器: from rest_framework.renderers import BrowsableAPIRenderer,AdminRenderer,HTMLFormRenderer,JSONRe ...
- CPCT精细化运营:客户、产品、渠道、时机
关键词:CPCT.精细化运营思维.客户.产品.渠道.时机.运营 电信运营商市场饱和,用户新增主要靠弃卡后重新入网以及异网用户策反. 用户新增已如此艰难,所以更加关注存量用户经营. 运营商营销资源不断收 ...
- 关于Vue中,checkBox等组件在赋值后,点击切换页面未及时更新问题
我们经常碰到这样的问题,在v-for循环中,给某些组件(此处以checkBox为例)赋值后,组件并不能正常切换, 这是因为数据层太多,render函数没有自动更新,需手动强制刷新. 解决方法:在切换c ...
- nodejs入门API之fs模块
fs模块下的类与FS常量 fs模块下的主要方法 fs的Promise API与FileHandle类 一.fs模块下的类 1.1 fs.Dir:表示目录流的类,由 fs.opendir().fs.op ...
- iOS分类(category),类扩展(extension)—史上最全攻略
背景: 在大型项目,企业级开发中多人同时维护同一个类,此时程序员A因为某项需求只想给当前类currentClass添加一个方法newMethod,那该怎么办呢? 最简单粗暴的方式是把newMethod ...
- ASE19团队项目 beta阶段 model组 scrum2 记录
本次会议于12月3日,19时整在微软北京西二号楼sky garden召开,持续10分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...