简单题(easy)
Description
有一个 n个元素的数组,每个元素初始均为 0。有 m条指令,要么让其中一段连续序列数字反转—— 0变 1,1变 0(操作 1),要么询问某个元素的值(操作 2)。
例如当 n = 20时,10条指令如下:
Input
第一行包含两个整数 n,m,表示数组的长度和指令的条数;
以下 m行,每行的第一个数 t表示操作的种类:
- 若 t = 1,则接下来有两个数 L, R,表示区间 [L, R]的每个数均反转;
- 若 t = 2,则接下来只有一个数 i,表示询问的下标。
Output
每个操作 2输出一行(非 0即 1),表示每次操作 2的回答。
Sample Input 1
20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6
Sample Output 1
1
0
0
0
1
1
Hint
对于 50%的数据,1 <= n <= 10^3, 1 <= m <= 10^4;
对于 100%的数据,1 <= n <= 10^5, 1 <= m <= 5*10^5,保证 L <= R。
题解:
树状数组+差分
区间修改+单点查询
刚接触树状数组,感觉有点难想,对于给出的边界[l,r],维护差分数组,对从l到n的位置进行+1操作,然后对r+1到n的位置进行-1操作,这样就不需要再做差了,这样得出的值便是单点查询的值,而不是原来的区间查询,然后用得到的sum去模2,看反转的次数,sum%2得到的结果就是最后的答案
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5+5;
int c[maxn],sum[maxn];
int n,m;
int lowbit(int x){
return x&(-x);
}
int getsum(int x){
int ans = 0;
while(x > 0){
ans += c[x];
x -= lowbit(x);
}
return ans;
}
void update(int x,int v){
while(x <= n){
c[x] += v;
x += lowbit(x);
}
}
int main(){
cin >> n >> m;
for(int i = 0 ; i < m ; i++){
int t;
cin >> t;
if(t == 1){
int l,r;
cin >> l >> r;
update(l,1),update(r+1,-1);
}else if(t == 2){
int k;
cin >> k;
cout << getsum(k)%2 << endl;
}
}
return 0;
}
I'm so cute. Please give me money.
- 本文链接:http://yoursite.com/2020/08/10/%E7%AE%80%E5%8D%95%E9%A2%98/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub IssuesGitHub Discussions