洛谷 P4969 神秘的703 题解

PART 0:前言

这是学长出的一道题目,非常的毒瘤。高精度 + 树状数组,而且还有几个非常搞人的操作。当时 Tingtime 老师(没错,就是我们的信奥老师)给我们放到了模拟考试里,直接就爆零了(这里的数据比我们 OJ 上的友好多了)。

本题解同步发表在我的个人博客

PART 1:解题思路

看到这一题有单点修改和区间查询,我们第一个想到的肯定是线段树或者树状数组实现。这一点是毋庸置疑的。但是我们看到题目中给出的数据范围:

输入数据在整型范围内

貌似是不用高精度的,但是如果你想想 Guy 的操作,是乘法对不对?两个整型范围内的数相乘,答案显然是存不下的。当然,你可以写高精度,这肯定是对的,但是会很麻烦(或许吧,不过我是这样觉得的)。但是有一种更简单的方法:超出标记。什么意思呢?由于其他人的操作都不可能使数据超出整型范围,所以我们可以对超出长整型的范围的数进行标记。由于超出了范围,所以除了 Tingtime 老师直接调整难度,其他人的操作都几乎不会有影响,同时这道题目 ZeroMike 是肯定做不出的。所以,我们只要加一个标记,标记这道题的难度是否超过了长整型的范围,如果超过了,标记一下,直到 Tingtime 老师调整难度之后才将标记归零。而在其他操作的时候,判定一下标记,如果标记了,那么对其的操作就是无意义的。

有了这个操作,可以省去很多繁琐的操作。码长 - -,时间 - -。

细节

但是,这道题目还有一个小小的细节需要注意,这个问题很容易忽略。(我看学长的题解貌似没有写到?)

谁说 Tingtime 老师只会调低难度了?

所以,你不仅需要判断 Tingtime 老师调低难度的事件,还要判断他调高难度的事件。这可能是这题最坑的点了。

PART 2: AC 代码

不说了,下面放上 AC 代码

#include<bits/stdc++.h>
using namespace std;
struct node{
    long long val;
    bool flag;//标记是否越界
};
struct things{
    char opt[20];
    long long mark,val;
};
things th;
node hard[500010];
long long n,talent,m;
long long num;
long long sum[500010];
//树状数组基本操作
long long lowbit(long long x){
    return x&(-x);
}
void updata(long long i,long long x){
    while(i<=n){
        sum[i]+=x;
        i+=lowbit(i);
    }
}
long long get_sum(long long i){
    long long res=0;
    while(i>0){
        res+=sum[i];
        i-=lowbit(i);
    }
    return res;
}
int main(){
    // freopen("room.in","r",stdin);
    // freopen("room.ans","w",stdout);
    scanf("%lld%lld",&n,&talent);
    for(long long i=1;i<=n;i++){
        scanf("%lld",&hard[i].val);
        if(hard[i].val<=talent){
            updata(i,1);
        }
        hard[i].flag=false;
    }
    scanf("%lld",&m);
    while(m--){
        scanf("%s %lld %lld",th.opt,&th.mark,&th.val);
        if(th.opt[0]=='Z'){
            if(th.mark>th.val) swap(th.mark,th.val);
            printf("%lld\n",(long long)600*(get_sum(th.val)-get_sum(th.mark-1)));
        }else if(th.opt[0]=='t'){
            if((hard[th.mark].val>talent||hard[th.mark].flag)&&th.val<=talent) updata(th.mark,1);//调低难度
            else if((hard[th.mark].val<=talent&&hard[th.mark].flag==false)&&th.val>talent) updata(th.mark,-1);//调高难度,很坑,但很真实
            hard[th.mark].val=th.val;
            hard[th.mark].flag=false;
        }else if(th.opt[0]=='B'){
            //如果越界了再减是没有意义的,不可能减到范围内
            if(!hard[th.mark].flag){
                if(hard[th.mark].val>talent&&hard[th.mark].val-th.val<=talent){
                    updata(th.mark,1);
                }
                hard[th.mark].val-=th.val;
                if(hard[th.mark].val<1) hard[th.mark].val=1;
            }
        }else if(th.opt[0]=='G'){
            //越界了也没有必要再乘
            if(!hard[th.mark].flag){
                if(hard[th.mark].val<=talent&&(hard[th.mark].val*th.val>talent||hard[th.mark].val*th.val<0)){
                    updata(th.mark,-1);
                }
                hard[th.mark].val*=th.val;
                //标记
                if(hard[th.mark].val<=0){
                    hard[th.mark].flag=1;
                    hard[th.mark].val=-1;
                }
            }
        }
    }
    return 0;
}
posted @ 2022-02-10 10:08  Night_Tide  阅读(103)  评论(0)    收藏  举报