0%

P5057 [CQOI2006] 简单题

思路讲解

和这题代码基本一样,还是比较适合我复训的。

我们来解释一下为什么可以这样pushup

1
2
3
4
5
6
inline void invert(ll s,ll e){
pushup(s, 1);
if(e<n){
pushup(e+1, -1);
}
}

众所周知,我们知道差分数组是给diff[s]+1,给diff[e+1]-1,那为什么可以直接pushup那?那是因为树状数组中遍历你上面的数组是必然遍历不到你的,这点你不用担心,所以不用担心差分连续加导致出错。

AC代码

https://www.luogu.com.cn/record/192393560

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <iterator>
#include <random>
#include <iomanip>
// 树状数组
using namespace std;
typedef long long ll;
const ll N=static_cast<ll>(5e5)+10;
ll n,m,tr[N];
inline ll mod2(ll x){ // 对2取模
return (x+2)%2;
}
inline ll lowbit(ll x){
// 负数补码原理,负数就是把你之前的书全部取反再加1
// 正数和0的补码就是该数字本身再补上最高比特0
// 负数的补码则是将其绝对值按位取反再加1。
return x&(-x);
}
inline void pushup(ll x,ll v){
while(x<n+1){
tr[x]+=v;
x+=lowbit(x);
}
}
//
inline void invert(ll s,ll e){
pushup(s, 1);
if(e<n){
pushup(e+1, -1);
}
}

inline ll search(ll x){
if(x==0) return 0;
return search(x-lowbit(x))+tr[x];
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
while(m--){
ll op;
cin>>op;
if(op==1){
ll s,e;
cin>>s>>e;
invert(s, e);
}else{
ll x;
cin>>x;
cout<<mod2(search(x))<<endl;
}
}
return 0;
}
// AC https://www.luogu.com.cn/record/192393560

心路历程(WA,TLE,MLE……)