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;
}
- 怪事
现在还不会,以后更新
$$Life \quad is \quad fantastic!$$