【CF954G】 Castle Defense

题目

题目描述
Today you are going to lead a group of elven archers to defend the castle that is attacked by an army of angry orcs. Three sides of the castle are protected by impassable mountains and the remaining side is occupied by a long wall that is split into nn sections. At this moment there are exactly a_{i}a
i

archers located at the ii -th section of this wall. You know that archer who stands at section ii can shoot orcs that attack section located at distance not exceeding rr , that is all such sections jj that |i-j|<=r∣i−j∣<=r . In particular, r=0r=0 means that archers are only capable of shooting at orcs who attack section ii .

Denote as defense level of section ii the total number of archers who can shoot at the orcs attacking this section. Reliability of the defense plan is the minimum value of defense level of individual wall section.

There is a little time left till the attack so you can’t redistribute archers that are already located at the wall. However, there is a reserve of kk archers that you can distribute among wall sections in arbitrary way. You would like to achieve maximum possible reliability of the defence plan.

输入格式
The first line of the input contains three integers nn , rr and kk ( 1<=n<=5000001<=n<=500000 , 0<=r<=n0<=r<=n , 0<=k<=10^{18}0<=k<=10
18
) — the number of sections of the wall, the maximum distance to other section archers can still shoot and the number of archers yet to be distributed along the wall. The second line contains nn integers a_{1},a_{2},…,a_{n}a
1

,a
2

,…,a
n

( 0<=a_{i}<=10^{9}0<=a
i

<=10
9
) — the current number of archers at each section.

输出格式
Print one integer — the maximum possible value of defense plan reliability, i.e. the maximum possible value of minimum defense level if we distribute kk additional archers optimally.

题意翻译
一共有 nn 面墙,初始有 a_ia
i

个弓箭手在第 ii 面墙的位置上。一个在 ii 位置的弓箭手可以保护 |i - j| \leq r∣i−j∣≤r 的所有墙 jj 。

你现在可以增派 kk 个弓箭手并且任意分配它们的位置。你需要最大化被数量最少的弓箭手保护的墙被弓箭手保护的数量。

n \leq 5 \times 10^5, 0 \leq r \leq n, 0 \leq k \leq 10^{18} ,0 \leq a_i \leq 10^9n≤5×10
5
,0≤r≤n,0≤k≤10
18
,0≤a
i

≤10
9

输入输出样例
输入 #1复制
5 0 6
5 4 3 4 9
输出 #1复制
5
输入 #2复制
4 2 0
1 2 3 4
输出 #2复制
6
输入 #3复制
5 1 1
2 1 2 1 2
输出 #3复制
3

思路

二分答案

对于每个城墙i 都有ai个弓箭手,可以守卫左右各r的范围, 其实就是在(i-r)——(i+r)这段区间内都有ai个守备力量,就是在其间每个点+ai

再去思考如何验证一个答案X

从左到右遍历,若一个点i的值(bi)不足X,就将以i为起点向右的一段长度为2*r的区间都加上(x-bi)(因为左边已满足条件,贡献给右边)

若需要加的值超过k(可用的弓箭手),则答案不行

用差分与前缀和之类的去考虑,这样区间加值就是在区间首+x,区间尾后面-x;

代码

#include <bits/stdc++.h>
#define inf 500000077
using namespace std;
struct node
{
	int d1,d2,d3,d4;
}a[800001];
bool mp[3][200001];
node add(node a,node b)
{
	node c;
	c.d1=min(inf,min(a.d1+b.d1,a.d3+b.d4)+1);
	c.d2=min(inf,min(a.d2+b.d2,a.d4+b.d3)+1);
	c.d3=min(inf,min(a.d3+b.d2,a.d1+b.d3)+1);
	c.d4=min(inf,min(a.d4+b.d1,a.d2+b.d4)+1);
	return c;
}
void build(int l,int r,int k)
{
	if(l==r)
	{
		a[k].d1=a[k].d2=a[k].d3=a[k].d4=inf;
		if(mp[1][l]) a[k].d1=0;
		if(mp[2][l]) a[k].d2=0;
		if(mp[1][l]&&mp[2][l]) a[k].d3=a[k].d4=1;
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	a[k]=add(a[k*2],a[k*2+1]);
	return;
}
node get(int L,int R,int l,int r,int k)
{
	if(L<=l&&R>=r)
		return a[k];
	int mid=(l+r)/2;
	node b,c;
	bool q1=0,q2=0;
	if(L<=mid) q1=1,b=get(L,R,l,mid,k*2);
	if(R>mid) q2=1,c=get(L,R,mid+1,r,k*2+1);
	if(q1&&!q2) return b;
	if(!q1&&q2) return c;
	if(q1&&q2) return add(b,c);
}
int main()
{
	int n,m,ans;
	char p;
	int xa,xb,ya,yb;
	node k;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=2; i++)
		for(int j=1; j<=n; j++)
		{
			cin>>p;
			if(p=='.') mp[i][j]=1;
		}
	build(1,n,1);
	for(int i=1; i<=m; i++)
	{
		xa=1;xb=1;
		scanf("%d%d",&ya,&yb);
		if(ya>n) 
		{
			ya-=n; xa=2;
		}
		if(yb>n) 
		{
			yb-=n; xb=2;
		}
		if(ya>yb) 
		{
			swap(xa,xb); swap(ya,yb);
		}
		k=get(ya,yb,1,n,1);
		if(xa==xb&&xa==1) ans=k.d1;
		else if(xa==xb&&xa==2) ans=k.d2;
		else if(xa>xb) ans=k.d4;
		else ans=k.d3;
		if(ans<inf) printf("%d\n",ans);
		else printf("-1\n");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值