2019.4.11训练

codeforces938d

首先我们观察这道题:本质是一个最短路问题,但是它问的是对每个i,求2*d(i,j)+ai[i];

首先如果这样一搞的话我们还是挺容易就想到,把它的每条边都乘以2倍的。但是这样的话我们又无法把ai[i]这个给算进去。这样一来的话我们可以变化着处理一下。

我们弄一个源节点为0,从0出发向1到n每个点引一条最边。这样从0出发,跑一次单源最短路我们就可以求得到其他点的距离最小值,我们只要这样一搞的话,便可以很轻易的找到最小值。。。。。。。。。。。。。

同样:我觉得这个不是很难想,但是我为什么考场没有想到啊。。。。。。。。

这个2倍是很容易想的,这个虚构一个点也不是很难想啊。。。。。。。

主要是要想到怎么跑一遍单源最短路,这样你才会想到来重构这个图!!!!!!!!!!!!!!!!!!!!!!!!!!!!

下面是代码:

 1 #include <algorithm>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <bitset>
 7 #include <vector>
 8 #include <queue>
 9 typedef long long ll;
10 using namespace std;
11 const int maxn=200100;
12 int n,m;
13 const ll inf=1e15+1000;
14 ll ai[maxn];
15 struct node{
16     int to;
17     ll w;
18     node(int a,ll b):to(a),w(b){}
19 };
20 
21 struct qnode{
22     int now;
23     ll dis;
24     qnode(int a,ll b):now(a),dis(b){}
25     bool operator <(const qnode &r) const{
26         return dis>r.dis;
27     }
28 };
29 
30 ll dis[maxn];
31 int vis[maxn];
32 vector<node> G[maxn];
33 
34 void dijkstra(){
35      for(int i=1;i<=n;i++) dis[i]=inf;
36      for(int i=1;i<=n;i++) vis[i]=0;
37      dis[0]=0;
38      priority_queue<qnode> que;
39      que.push(qnode(0,0));
40      while(!que.empty()){
41          qnode tmp=que.top();
42          que.pop();
43          int  now=tmp.now;
44          if(vis[now]==1) continue;
45          vis[now]=1;
46          //printf("%d %d sbsbsbsb\n",now,G[now].size());
47          for(int i=0;i<G[now].size();i++){
48              int v=G[now][i].to;
49              ll cost=G[now][i].w;
50              //printf("%d  %lld sbsbsb\n",v,dis[v]);
51              if(vis[v]==0&&dis[v]>dis[now]+cost){
52                  //printf("%d  %lld sbsbsb\n",v,dis[v]);
53                  dis[v]=dis[now]+cost;
54                  que.push(qnode(v,dis[v]));
55              }
56          }
57      }
58      for(int i=1;i<n;i++) printf("%lld ",dis[i]);
59      printf("%lld\n",dis[n]);
60 }
61 
62 int main(){
63     scanf("%d%d",&n,&m);
64     for(int i=1;i<=m;i++){
65         int u,v;
66         ll w;
67         scanf("%d%d%lld",&u,&v,&w);
68         G[u].push_back(node(v,2*w));
69         G[v].push_back(node(u,2*w));
70     }
71     for(int i=1;i<=n;i++) scanf("%lld",&ai[i]);
72     for(int i=1;i<=n;i++)  G[0].push_back(node(i,ai[i]));
73     dijkstra();
74     return 0;
75 }
View Code

codeforces939E

首先这道题给你的条件你得注意,这个x是递增的,所以你最后一个数是一定得取的,然后你就会发现一点我们要取数的话,肯定是要是取前面的那个小的数,这样平均值才会越来越来,然后列出来一下公式,随便随便搞搞,前一项减去后一项,就会发现这是一个3分函数,得3分,然后这道题就结束了啊。。。。。。。。。。。。。。。。。。

下面是代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <bitset>
 6 #include <algorithm>
 7 typedef long long ll;
 8 using namespace std;
 9 const int maxn=500100;
10 int q;
11 int tip;
12 ll x;
13 int tot=0;
14 ll sum[maxn];
15 ll num[maxn];
16 ll l,r;
17 
18 double f(ll mid){
19     return (double)num[tot]-(double)((sum[mid]+num[tot])/(double)(mid+1));
20 }
21 
22 int main(){
23     scanf("%d",&q);
24     sum[0]=0;
25     while(q--){
26         scanf("%d",&tip);
27         if(tip==1){
28            tot++;
29            scanf("%lld",&num[tot]);
30            sum[tot]=sum[tot-1]+num[tot];
31         }else{
32            l=1;
33            r=tot-1;
34            while(r-l>2){
35                ll lmid=l+(r-l)/3;
36                ll rmid=r-(r-l)/3;
37                if(f(lmid)>f(rmid)){
38                    r=rmid;
39                }else if(f(lmid)<f(rmid)){
40                    l=lmid;
41                }else{
42                    l=lmid;
43                    r=rmid;
44                }
45            }
46            double ans=0.0;
47            for(ll j=l;j<=r;j++) ans=max(ans,f(j));
48            printf("%.10lf\n",ans);
49         }
50     }
51     return 0;
52 }
View Code

猜你喜欢

转载自www.cnblogs.com/pandaking/p/10692166.html