P6619 [省选联考 2020 A/B 卷] 冰火战士

P6619 [省选联考 2020 A/B 卷] 冰火战士

  • \(10pts\)

不离散化,直接暴力

  • \(20pts\)

最优解一定在某个战士的温度值取到。

这就是考场上导致我没有想出\(60pts\)的原因(第二个就是没注意到2操作也要输出答案,浪费\(1\)个小时\(debug\)

暴力枚举温度,暴力更新即可

复杂度:\(O(Q^2)\),期望得分:\(20pts\)

  • \(60pts\)

树状数组+二分

还是先可以离散化一下温度,设\(I[t]\)为在\(t\)温度下冰战士的能量和,\(F[t]\)是火战士的能量和,答案就是\(2\cdot\min(I(t),F(t))\)

则显然有\(I(t)\)单调不降\(F(t)\)单调不增

我们可以二分一个\(I(t)\)\(F(t)\)最接近的合适的温度,分别用两个树状数组维护冰和火战士(一个前缀和,一个后缀和)

复杂度为\(O(Q*log^2Q)\),期望得分:\(60pts\)

/*
@ author:pyyyyyy/guhl37
-----思路------

-----debug-------

*/
#include<bits/stdc++.h>
#include<map>
using namespace std;
int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
const int N=2000010;
int q[N],tot,n;
struct node {
	int k,x,y;
} a[N];
map<int,int> ma;
int tr[2][N];
int lowbit(int x) {
	return x&-x;
}
void add(int k,int x,int val) {
	for(; x<=tot; x+=lowbit(x)) tr[k][x]+=val;
}
int query(int k,int x) {
	int ret = 0;
	for( ; x ; x -= lowbit(x)) ret += tr[k][x];
	return ret;
}
int check(int x) {
	return query(0,x)>=query(1,tot)-query(1,x-1);
}
int main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n=read();
	for(int i=1,opt; i<=n; ++i) {
		opt=read();
		if(opt==1) a[i].k=read(),a[i].x=read(),a[i].y=read(),q[++tot]=a[i].x;
		else a[i].k=read();
	}
	/*离散化*/
	sort(q+1,q+1+tot);
	tot=unique(q+1,q+1+tot)-q-1;
	for(int i=1; i<=tot; ++i) ma[q[i]]=i;
	for(int i=1; i<=n; ++i) if(a[i].x) a[i].x=ma[a[i].x];
	for(int i=1; i<=n; ++i) {
		if(a[i].x) add(a[i].k,a[i].x,a[i].y);
		else add(a[a[i].k].k,a[a[i].k].x,-a[a[i].k].y);
		int l=1,r=tot;//二分位置
		while(l<r) {
			int mid=(l+r)>>1;
			if(check(mid)) r=mid;
			else l=mid+1;
		}
		int ans2=query(0,l-1),ans1=query(1,tot)-query(1,l-1);
		if(!ans1&&!ans2) printf("Peace\n");
		else if(ans1<ans2) printf("%lld %lld\n",q[l-1],ans2<<1);
		else {
			for(int j=log2(tot)+1; j>=0; --j) {
				int k=l+(1<<j);
				if(k>tot) continue;
				if(query(1,tot)-query(1,k-1)==ans1) l=l+(1<<j);
			}
			printf("%lld %lld\n",q[l],ans1<<1);
		}
	}
	return 0;
}
  • 怪事

本地运行结果

在线测试结果
- $100pts$

现在还不会,以后更新

posted @ 2020-07-01 21:01  pyyyyyy  阅读(329)  评论(0编辑  收藏  举报