线段树格式
struct sgt{
node t[N*4];
int tag[N*4];
void push_up(int p){
}
void push_down(int p){
}
void build(int p,int l,int r){
}
void update(int p,int begin,int end,int l,int r){
}
int query(int p,int begin,int end,int l,int r){
}
}t;
五大函数:建树、更新、查询、以下推上、以上传下。
写出这五大函数,一道线段树的题目就写完了。
考虑子状态的转移,推导出父节点状态即可。
AC 代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1000000+10;
struct node{
int n,t;
};
struct sgt{
node t[N*4];
int tag[N*4];
void push_up(int p){
t[p].n = t[p*2+1].n+t[p*2].n;
t[p].t = t[p*2+1].t+t[p*2].t;
}
void swaper(int p){
swap(t[p].n,t[p].t);
}
void push_down(int p){
if(tag[p]){
swaper(p*2);
swaper(p*2+1);
tag[p] = 0;
tag[p*2]++;
tag[p*2]%=2;
tag[p*2+1]++;
tag[p*2+1]%=2;
}
}
void build(int p,int l,int r){
if(l == r){
t[p].n = 1;
return ;
}
int mid = (l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void update(int p,int begin,int end,int l,int r){
push_down(p);
if(l == begin&&r == end){
swap(t[p].n,t[p].t);
tag[p]++;
tag[p]%=2;
return;
}
int mid = (begin+end)/2;
if(r <= mid){
update(p*2,begin,mid,l,r);
}
else if(l > mid){
update(p*2+1,mid+1,end,l,r);
}
else{
update(p*2,begin,mid,l,mid);
update(p*2+1,mid+1,end,mid+1,r);
}
push_up(p);
//cout<<p<<" "<<begin<<" "<<end<<" "<<l<<" "<<r<<" "<<t[p].t<<endl;
}
int query(int p,int begin,int end,int l,int r){
push_down(p);
if(l == begin&& r==end){
return t[p].t;
}
int mid = (begin+end)/2;
if(r <= mid){
return query(p*2,begin,mid,l,r);
}
else if(l > mid){
return query(p*2+1,mid+1,end,l,r);
}
else{
return query(p*2,begin,mid,l,mid)+query(p*2+1,mid+1,end,mid+1,r);
}
}
}t;
int main(){
int n,m;
cin>>n>>m;
t.build(1,1,n);
for(int i = 1;i <= m;i++){
int c,a,b;
cin>>c>>a>>b;
if(c==0){
t.update(1,1,n,a,b);
}
else{
cout<<t.query(1,1,n,a,b)<<endl;
}
}
return 0;
}