20191029
前言
- 终于因为没有define int longlong挂分了……
- 自己还是对扩欧理解不深刻,板子都不会只能现场yy,还打错了。
- T2T3没有思路,还是没有培养思维。
T1
- 用扩展欧几里得求方程的解。
- 先将x,y其中一个值变成最靠近0的情况,然后暴力寻找更优解就行了。
- 注意扩欧板子中要用a/b*x而不是x*a/b。
#include<cstdio> #define ll long long using namespace std; int c; inline int read(){ int ss(0),pp(1);char bb(getchar()); for(;bb<48||bb>57;bb=getchar())if(bb=='-')pp=-1; while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return ss*pp; } int exgcd(int a,int b,ll &x,ll &y){ if(!b){ x=1,y=0; return a; } int z=exgcd(b,a%b,y,x); y-=a/b*x; return z; } inline ll _abs(ll x){ return x<0?-x:x; } signed main(){ //freopen("array.in","r",stdin); //freopen("1.out","w",stdout); int n=read(),a=read(),b=read(),g; if(a>b)a^=b^=a^=b; ll x,y,ans=0; g=exgcd(a,b,x,y); a/=g,b/=g; for(register int i=1;i<=n;++i){ c=_abs(read()); if(c%g)return puts("-1"),0; c/=g; ll zx=x*c,zy=y*c,z=zx/b; zx-=z*b,zy+=z*a; while(_abs(zx)+_abs(zy)>_abs(zx-b)+_abs(zy+a))zx-=b,zy+=a; while(_abs(zx)+_abs(zy)>_abs(zx+b)+_abs(zy-a))zx+=b,zy-=a; ans+=_abs(zx)+_abs(zy); } printf("%lld",ans); return 0; }
T2
- 先将给出的点对$(a_i,b_i)$按$a_i+b_i$的大小排序,然后就是一个队长快跑。
#include<cstdio> #include<algorithm> #include<queue> #define ll long long #define L tr[k].lc #define R tr[k].rc #define LC k<<1 #define RC k<<1|1 using namespace std; int const N=2e5+5; int n,tot; struct node{ int a,b,w; node(){} node(int x,int y,ll z):a(x),b(y),w(z){} friend bool operator < (node skyh,node yxs){ return (skyh.a^yxs.a)?skyh.a>yxs.a:skyh.w<yxs.w; } }s[N]; struct Pair{ int fr,sc; Pair(){} Pair(int x,int y):fr(x),sc(y){} }c[N]; int tt; inline int read(){ int ss(0);char bb(getchar()); while(bb<48||bb>57)bb=getchar(); while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return ss; } inline ll _max(ll x,ll y){ return x>y?x:y; } struct Segment_Tree{ struct ljj{ int lc,rc; ll val,f; }tr[N<<2]; void down(int k){ int lk=k<<1;ll z=tr[k].f; tr[k].f=0; tr[lk].val+=z,tr[lk].f+=z; lk|=1,tr[lk].val+=z,tr[lk].f+=z; return ; } void build(int x,int y,int k){ L=x,R=y; if(x==y)return ; int mid=x+y>>1; return build(x,mid,LC),build(mid+1,y,RC); } void add(int x,int y,ll z,int k){ if(L>=x&&R<=y){tr[k].val+=z,tr[k].f+=z;return ;} int mid=L+R>>1; if(tr[k].f)down(k); if(x<=mid)add(x,y,z,LC); if(y>mid)add(x,y,z,RC); tr[k].val=_max(tr[LC].val,tr[RC].val); return ; } void modify(int x,ll y,int k){ if(L==R){tr[k].val=_max(y,tr[k].val);return ;} if(tr[k].f)down(k); modify(x,y,k<<1|(x>(L+R>>1))); tr[k].val=_max(tr[LC].val,tr[RC].val); return ; } ll ask(int x,int y,int k){ if(L>=x&&R<=y)return tr[k].val; int mid=L+R>>1; if(tr[k].f)down(k); if(x<=mid)return _max(ask(x,y,k<<1),y>mid?ask(x,y,k<<1|1):0ll); return ask(x,y,k<<1|1); } }T; int main(){ //freopen("pair.in","r",stdin); //freopen("1.out","w",stdout); n=read(); for(register int i=1;i<=n;++i) c[++tt]=Pair(s[i].a=read(),(i<<1)-1), c[++tt]=Pair(s[i].b=read(),i<<1), s[i].w=read(); sort(c+1,c+tt+1,[](Pair skyh,Pair yxs){ return skyh.fr<yxs.fr; }); for(register int i=1;i<=tt;++i) ((c[i].sc&1)?s[c[i].sc+1>>1].a:s[c[i].sc+1>>1].b)=tot=tot+(c[i].fr!=c[i-1].fr); sort(s+1,s+n+1,[](node skyh,node yxs){ return skyh.a+skyh.b<yxs.a+yxs.b; }); T.build(1,tot,1); for(register int i=1;i<=n;++i){ if(s[i].a<s[i].b)T.add(s[i].a+1,s[i].b,s[i].w,1); T.modify(s[i].a,T.ask(1,min(s[i].a,s[i].b),1)+s[i].w,1); } return printf("%lld",T.tr[1].val),0; }
T3
- 多源最短路啊……思路很不错。
- 记录每个节点的前驱,如果一条边的两个端点的前驱不同就更新答案。
#include<cstdio> #include<cstring> #define ll long long using namespace std; int const N=2e5+5; ll const lar=1e18; int n,m,p; int head[N],Next[N<<1],to[N<<1],w[N<<1],t=1; int q[N]; struct Pair{ int id; ll wt; Pair(){} Pair(int x,ll y):id(x),wt(y){} }hp[N]; int tp,pre[N]; bool vis[N]; ll dis[N],ans[N]; inline int read(){ int ss(0);char bb(getchar()); while(bb<48||bb>57) bb=getchar(); while(bb>=48&&bb<=57) ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return ss; } inline void add(int x,int y,int z){ to[++t]=y,w[t]=z; Next[t]=head[x],head[x]=t; return ; } inline void _Swap(Pair &x,Pair &y){ Pair z=x; x=y,y=z; return ; } inline void up(int x){ while(x^1){ if(hp[x].wt<hp[x>>1].wt) _Swap(hp[x],hp[x>>1]),x>>=1; else return ; } } inline void down(int x){ int y=x<<1; while(y<=tp){ if(y^tp && hp[y].wt>hp[y|1].wt) y|=1; if(hp[x].wt>hp[y].wt) _Swap(hp[x],hp[y]),x=y,y<<=1; else return ; } } inline void dijkstra(){ while(tp){ int x=hp[1].id; ll y=hp[1].wt; _Swap(hp[1],hp[tp--]),down(1); if(vis[x])continue; vis[x]=1; for(register int i=head[x],pnw=pre[x];i;i=Next[i]) if(dis[to[i]]>y+w[i]) pre[to[i]]=pnw,hp[++tp]=Pair(to[i],dis[to[i]]=y+w[i]),up(tp); } return ; } int main(){ //freopen("distance.in","r",stdin); n=read(),m=read(),p=read(); for(register int i=1;i<=p;++i) ans[q[i]=read()]=lar; for(register int i=1,ff,tt,ww;i<=m;++i) ff=read(),tt=read(),ww=read(), add(ff,tt,ww),add(tt,ff,ww); memset(dis,0x3f,n+1<<3); for(register int i=1;i<=p;++i) hp[i]=Pair(q[i],dis[q[i]]=0),pre[q[i]]=q[i]; tp=p; dijkstra(); for(register int i=1;i<=m;++i){ int z=i<<1,x=to[z],y=to[z|1]; if(pre[x]==pre[y])continue; ll le=dis[x]+dis[y]+w[z]; x=pre[x],y=pre[y]; if(le<ans[x])ans[x]=le; if(le<ans[y])ans[y]=le; } for(register int i=1;i<=p;++i)printf("%lld ",ans[q[i]]); return 0; }
rp++