題面:https://www.cnblogs.com/Juve/articles/11767225.htmlhtml
數列:node
簡化題意:已知a,b,c,求知足$a*x+b*y=c$的$x+y$最小值ios
而後ex_gcd硬剛就行了,若c爲負,則取abs數組
若是咱們設a<b,最優決策點就是x的最小正整數解和最大負整數解ide
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e5+5; 8 int n,a,b,g,val,x,y,ans=0; 9 int ex_gcd(int a,int b,int &x,int &y){ 10 if(!b){ 11 x=1,y=0; 12 return a; 13 } 14 int d=ex_gcd(b,a%b,x,y); 15 int t=x; 16 x=y,y=t-a/b*x; 17 return d; 18 } 19 signed main(){ 20 scanf("%lld%lld%lld",&n,&a,&b); 21 if(a>b) swap(a,b); 22 g=ex_gcd(a,b,x,y); 23 a/=g,b/=g; 24 x=(x%b+b)%b; 25 for(int i=1;i<=n;++i){ 26 scanf("%lld",&val); 27 if(val<0) val=-val; 28 if(val%g){ 29 puts("-1"); 30 return 0; 31 } 32 val/=g; 33 int p=(x*val%b+b)%b; 34 int q=(val-a*p)/b; 35 ans+=min(abs(p)+abs(q),abs(p-b)+abs(q+a)); 36 } 37 printf("%lld\n",ans); 38 return 0; 39 }
數對:spa
隊長快跑加了權值code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e5+5; 8 int n,ans=0,sta[MAXN<<1],top=0; 9 struct node{ 10 int a,b,w; 11 friend bool operator < (node p,node q){ 12 return p.a+p.b<q.a+q.b; 13 } 14 }p[MAXN]; 15 int tr[MAXN<<3],laz[MAXN<<3]; 16 void down(int k){ 17 tr[k<<1]+=laz[k],tr[k<<1|1]+=laz[k]; 18 laz[k<<1]+=laz[k],laz[k<<1|1]+=laz[k]; 19 laz[k]=0; 20 } 21 int query(int k,int l,int r,int opl,int opr){ 22 if(opl<=l&&r<=opr) return tr[k]; 23 if(laz[k]) down(k); 24 int mid=(l+r)>>1,res=0; 25 if(opl<=mid) res=max(res,query(k<<1,l,mid,opl,opr)); 26 if(opr>mid) res=max(res,query(k<<1|1,mid+1,r,opl,opr)); 27 return res; 28 } 29 void update(int k,int l,int r,int opl,int opr,int val){ 30 if(opl<=l&&r<=opr){ 31 tr[k]+=val; 32 laz[k]+=val; 33 return ; 34 } 35 if(laz[k]) down(k); 36 int mid=(l+r)>>1; 37 if(opl<=mid) update(k<<1,l,mid,opl,opr,val); 38 if(opr>mid) update(k<<1|1,mid+1,r,opl,opr,val); 39 tr[k]=max(tr[k<<1],tr[k<<1|1]); 40 } 41 void change(int k,int l,int r,int opt,int val){ 42 if(l==r){ 43 tr[k]=max(tr[k],val); 44 return ; 45 } 46 if(laz[k]) down(k); 47 int mid=(l+r)>>1; 48 if(opt<=mid) change(k<<1,l,mid,opt,val); 49 else change(k<<1|1,mid+1,r,opt,val); 50 tr[k]=max(tr[k<<1],tr[k<<1|1]); 51 } 52 signed main(){ 53 //freopen("pair.in","r",stdin); 54 scanf("%lld",&n); 55 for(int i=1;i<=n;++i){ 56 scanf("%lld%lld%lld",&p[i].a,&p[i].b,&p[i].w); 57 sta[++top]=p[i].a,sta[++top]=p[i].b; 58 } 59 sort(p+1,p+n+1); 60 sort(sta+1,sta+top+1); 61 top=unique(sta+1,sta+top+1)-sta-1; 62 for(int i=1;i<=n;++i){ 63 p[i].a=lower_bound(sta+1,sta+top+1,p[i].a)-sta; 64 p[i].b=lower_bound(sta+1,sta+top+1,p[i].b)-sta; 65 } 66 for(int i=1;i<=n;++i){ 67 if(p[i].a<p[i].b){ 68 update(1,1,top,p[i].a+1,p[i].b,p[i].w); 69 int t=query(1,1,top,1,p[i].a)+p[i].w; 70 change(1,1,top,p[i].a,t); 71 }else{ 72 int t=query(1,1,top,1,p[i].b)+p[i].w; 73 change(1,1,top,p[i].a,t); 74 } 75 } 76 printf("%lld\n",tr[1]); 77 return 0; 78 }
最小距離:htm
多源點spfa,把全部特殊點做爲遠點跑spfa,此時的dis數組意義就是這個點到全部特殊點中最小那一個的距離,同時記錄這個點是從那一個點轉移而來,blog
跑完後枚舉全部邊,若是邊的兩段的點不是由同一個特殊點更新而來,那麼用dis[u]+dis[v]+val[u,v]更新兩個特殊點get
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define int long long using namespace std; const int MAXN=2e5+5; int n,m,p,x[MAXN]; int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],val[MAXN<<1],cnt=0,fr[MAXN<<1]; void add(int u,int v,int w){ ++cnt,to[cnt]=v,fr[cnt]=u,nxt[cnt]=pre[u],pre[u]=cnt,val[cnt]=w; } int dis[MAXN],fro[MAXN],ans[MAXN]; bool vis[MAXN]; queue<int>q; void spfa(){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i=1;i<=p;++i){ dis[x[i]]=0,vis[x[i]]=1; q.push(x[i]); fro[x[i]]=x[i]; } while(!q.empty()){ int x=q.front(); q.pop(); for(int i=pre[x];i;i=nxt[i]){ int y=to[i]; if(dis[y]>dis[x]+val[i]){ dis[y]=dis[x]+val[i]; fro[y]=fro[x]; if(!vis[y]) q.push(y),vis[y]=1; } } vis[x]=0; } } signed main(){ //freopen("distance.in","r",stdin); scanf("%lld%lld%lld",&n,&m,&p); for(int i=1;i<=p;++i) scanf("%lld",&x[i]); for(int i=1,u,v,w;i<=m;++i){ scanf("%lld%lld%lld",&u,&v,&w); add(u,v,w),add(v,u,w); } memset(ans,0x3f,sizeof(ans)); spfa(); for(int i=1;i<=cnt;i+=2){ int u=fr[i],v=to[i]; if(fro[u]!=fro[v]){ ans[fro[u]]=min(ans[fro[u]],dis[u]+dis[v]+val[i]); ans[fro[v]]=min(ans[fro[v]],dis[u]+dis[v]+val[i]); } } for(int i=1;i<=p;++i) printf("%lld ",ans[x[i]]); puts(""); return 0; }