csps模拟92数列,数对,最小距离题解

题面:https://www.cnblogs.com/Juve/articles/11767225.html

数列:

简化题意:已知a,b,c,求满足$a*x+b*y=c$的$x+y$最小值

然后ex_gcd硬刚就好了,若c为负,则取abs

如果我们设a<b,最优决策点就是x的最小正整数解和最大负整数解

 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 }
View 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 }
View Code

最小距离:

多源点spfa,把所有特殊点作为远点跑spfa,此时的dis数组意义就是这个点到所有特殊点中最小那一个的距离,同时记录这个点是从那一个点转移而来,

跑完后枚举所有边,如果边的两段的点不是由同一个特殊点更新而来,那么用dis[u]+dis[v]+val[u,v]更新两个特殊点

#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;
}

 

posted @ 2019-10-30 19:51  xukl21  阅读(218)  评论(0编辑  收藏  举报