洛谷 P4969 神秘的703 题解
PART 0:前言
这是学长出的一道题目,非常的毒瘤。高精度 + 树状数组,而且还有几个非常搞人的操作。当时 Tingtime 老师(没错,就是我们的信奥老师)给我们放到了模拟考试里,直接就爆零了(这里的数据比我们 OJ 上的友好多了)。
本题解同步发表在我的个人博客
PART 1:解题思路
看到这一题有单点修改和区间查询,我们第一个想到的肯定是线段树或者树状数组实现。这一点是毋庸置疑的。但是我们看到题目中给出的数据范围:
输入数据在整型范围内
貌似是不用高精度的,但是如果你想想 Guy 的操作,是乘法对不对?两个整型范围内的数相乘,答案显然是存不下的。当然,你可以写高精度,这肯定是对的,但是会很麻烦(或许吧,不过我是这样觉得的)。但是有一种更简单的方法:超出标记。什么意思呢?由于其他人的操作都不可能使数据超出整型范围,所以我们可以对超出长整型的范围的数进行标记。由于超出了范围,所以除了 Tingtime 老师直接调整难度,其他人的操作都几乎不会有影响,同时这道题目 Zero 和 Mike 是肯定做不出的。所以,我们只要加一个标记,标记这道题的难度是否超过了长整型的范围,如果超过了,标记一下,直到 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;
}

浙公网安备 33010602011771号