随手写个线段树来复习一下…..
线段树:只是带有区间查询,修改(1变0,0变1)通过^完成,建树
不解释,,,,
直接上代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
struct node
{
int num;
int l,r;
}tree[1000000];
void build(int l,int r,int h)
{
if(l==r)
{
tree[h].l=tree[h].r=l; //左右子树的范围是此时搜索的点个数
tree[h].num=0; //初始化为0
return;
}
tree[h].l=l;tree[h].r=r; //左右子树的范围是此时搜索的点个数
int mid=(l+r)>>1; //二分过程 l为左 r为右 <<指乘2 >>则反过来
build(l,mid,h<<1); //处理左边
build(mid+1,r,h<<1|1); //处理右边 <<1|1指乘2加一
tree[h].num=tree[h<<1].num+tree[h<<1|1].num; //合并数值
return;
}
int find(int l,int r,int h)
{
if(tree[h].l==l && tree[h].r==r)
return tree[h].num; //如果找的刚好是可以直接取的区间,则返回
int mid=(tree[h].l+tree[h].r)>>1; //算中点
if(r<=mid) //如果这段区间在右边,则往右边找
return find(l,r,h<<1);
if(l>mid) //如果这段区间在左边,则往左边找
return find(l,r,h<<1|1);
else//如果这段区间在中间,则隔开,左一端,右一段来找
return find(l,mid,h<<1)+find(mid+1,r,h<<1|1);
}
void update(int h,int l,int r)
{
if(tree[h].l==tree[h].r)
{
tree[h].num^=1; //修改
return ;
} //这个跟建树过程差不多
if(l<=(tree[h].l+tree[h].r)/2) update(h*2,l,r);
if(r>=(tree[h].l+tree[h].r)/2+1) update(h*2+1,l,r);
tree[h].num=tree[h*2].num+tree[h*2+1].num;
}
int main()
{
int i,j,k,m,n;
scanf("%d%d",&m,&n);
build(1,m,1); //建树
for(i=1;i<=n;i++)
{
int cmd,av1,av2;
scanf("%d%d%d",&cmd,&av1,&av2);
if(cmd==0)
update(1,av1,av2); //更新
if(cmd==1)
printf("%d\n",find(av1,av2,1)); //查找
}
return 0;
}