Loading

P6619 [省选联考 2020 AB 卷] 冰火战士

题面非常长,但是稍微思考一下发现就是求两边能量和的最小值的两倍。

容易想到离散化后用树状数组来维护每个温度上的能量情况(因为 \(n=2\times 10^6\),线段树解决常数太大会寄掉),那么只要解决查询就好了。

因为求的是最小值,而随着温度的上升,冰系战士能量和越来越大,火系战士能量和越来越小,所以找到它们差最小的地方就是答案了。

朴素做法是外面二分,里面套树状数组,但是两个 \(log\),又会死掉。

这时候我们学习了一个新知识:树状数组上二分!

根据树状数组的定义,\(c[i]\) 维护的区间是 \([i-lowbit(i)+1,i]\),所以只要像倍增一样一直跳,跳的过程中加上信息就好了。

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
struct node{
    int t,x,y;
}id[N];
int T,tot,len,sum,a[N],b1[N],b2[N],c1[N],c2[N];
int lowbit(int x){return x&-x;}
void add(int c[N],int x,int k)
{
    for(int i=x;i<=len;i+=lowbit(i))c[i]+=k;
    return;
}
void query()
{
    int p=0,s1=0,s2=0,k1=0,k2=0;
    for(int i=25;i>=0;i--)
    {
        if(p+(1<<i)>len)continue;
        if(s1+c1[p+(1<<i)]<=sum-(s2+c2[p+(1<<i)])+b2[p+(1<<i)])
        {
            s1+=c1[p+(1<<i)],s2+=c2[p+(1<<i)],p+=(1<<i);
        }
    }
    if(sum==0||(p==len&&s1==0)||(s1==0&&s2==sum))printf("Peace\n");
    else if(p==len)printf("%d %d\n",a[p],s1<<1);
    else if(s1>sum-s2)printf("%d %d\n",a[p],s1<<1);
    else 
    {
        s1+=b1[p+1],p=0;
        for(int i=25;i>=0;i--)
        {
            if(p+(1<<i)>len)continue;
            if(k2+c2[p+(1<<i)]-b2[p+(1<<i)]<=s2)k1+=c1[p+(1<<i)],k2+=c2[p+(1<<i)],p+=(1<<i);
        }
        printf("%d %d\n",a[p],(sum-s2)<<1);
    }
    return;
}
int main()
{
    scanf("%d",&T);
    for(int i=1,op;i<=T;i++)
    {
        scanf("%d",&op);
        if(op==1)scanf("%d%d%d",&id[i].t,&id[i].x,&id[i].y),a[++tot]=id[i].x;
        else scanf("%d",&id[i].t);
    }
    sort(a+1,a+1+tot);
    len=unique(a+1,a+1+tot)-a-1;
    for(int i=1;i<=T;i++)if(id[i].x)id[i].x=lower_bound(a+1,a+1+len,id[i].x)-a;
    for(int i=1;i<=T;i++)
    {
        if(id[i].x)
        {
            if(!id[i].t)add(c1,id[i].x,id[i].y),b1[id[i].x]+=id[i].y;
            else add(c2,id[i].x,id[i].y),b2[id[i].x]+=id[i].y,sum+=id[i].y;
        }
        else
        {
            int k=id[i].t;
            if(!id[k].t)add(c1,id[k].x,-id[k].y),b1[id[k].x]-=id[k].y;
            else add(c2,id[k].x,-id[k].y),b2[id[k].x]-=id[k].y,sum-=id[k].y;
        }
        query();
    }
    return 0;
}
posted @ 2025-07-19 14:48  AvisD  阅读(14)  评论(0)    收藏  举报