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