2019summer系列 第十场

https://vjudge.net/contest/312518#overview
请叫我掉分小王子,嘿嘿嘿~

A AtCoder 4924


用宽搜,把每个#加入队列,记录step就好了~
//暴力真的会超时,www
//不明白自己的输入输出哪里有问题。。就是会WA,换成cin就好了。。

B AtCoder 4925


大概有两种办法:从前往后算和从后往前算。
首先,行列状态是不互相影响的,所以可以变成一维的。
如果是从前往后,就需要计算每个人上下左右的步数的前缀和,并相互抵消,看看抵消之后会不会出边界~
如果是从后往前,就是倒着计算,从一个点开始,一个人想把这个点通过到处走成一个尽可能大的区间,另一个人想尽可能让点留在区间里,然后最后如果x落在区间里,就相当于走不出去,否则就是走得出去。

C AtCoder 4926


移走一个节点上的硬币,其实就相当于把树的直径减少1或者2,当直径为1的时候,移硬币的人会输(因为他没办法把硬币一下子拿完)。所以就~

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a,b,n,l,dis[200100],S;
vector<int> G[200100];
void dfs(int u,int f){
    dis[u]=dis[f]+1;
    for(int i=0;i<G[u].size();i++)
        if(G[u][i]!=f) dfs(G[u][i],u);
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1;i < n;i ++){
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	dfs(1,0);
    for(int i=1;i<=n;i++) if(dis[i]>dis[S]) S=i;  
    dfs(S,0);
    for(int i=1;i<=n;i++) l=max(l,dis[i]-1);
	if(l %3 == 1) cout <<"Second"<<endl;
	else cout<<"First"<<endl;
    return 0;
}

F CodeForces 954D


和之前某一道题很像哦!
正反求两遍,从s到各个点的距离,从n到各个点的距离。
然后对于每两个点i、j,如果
s − &gt; i 的 距 离 + t − &gt; j 的 距 离 s-&gt;i的距离+t-&gt;j的距离 s>i+t>j

s − &gt; j 的 距 离 + t − &gt; i 的 距 离 s-&gt;j的距离+t-&gt;i的距离 s>j+t>i
都大于
s 到 t 的 最 短 距 离 − 1 s到t的最短距离-1 st1
就可以修建公路!

G CodeForces 954G


二分答案+差分~

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,r,k,a[500500],b[500500],o,sum[500500],ss[500500],ans,x=9223372036854775807ll,y,mid,kk;
void makesum(){
	for(ll i = 1ll;i <= n;i ++)
		sum[i] = b[i]+sum[i-1ll];
}
int main(){
	ios::sync_with_stdio(false);
	cin>> n >> r >> k;
	for(ll i = 1ll;i <= n;i ++){
		cin>>o;
		a[max(1ll,i-r)] += o;
		a[min(i+r+1ll,n+1ll)] -= o;
	}
	for(ll i = 1ll;i <= n;i ++)
		sum[i] = a[i]+sum[i-1ll],x = min(x,sum[i]);
	y = x+k;
	while(x <= y){
		mid = (x+y)/2ll;
		kk = k;
		memset(b,0,sizeof b);
		for(ll i = 1ll;i <= n;i ++){
			ss[i] = ss[i-1]+a[i]+b[i];
			if(ss[i] < mid){
				b[i] += mid-ss[i];
				b[min(i+r+r+1ll,n+1ll)] -= mid-ss[i];
				kk -= mid-ss[i];
				if(kk < 0ll) break;
			}
			ss[i] = ss[i-1]+a[i]+b[i];
		}
		if(kk < 0ll) y = mid-1ll;
		else {
			ans = mid;
			x = mid+1ll;
		}
	}
	cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值