您的位置:首页 > 其它

bzoj1230: [Usaco2008 Nov]lites 开关灯(线段树)

2018-01-20 16:19 330 查看
题目传送门

…..

解法:

裸线段树。。

打个lazy。。

代码实现:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node {int l,r,lc,rc,c,n,lazy;}tr[210000];int len;
void bt(int l,int r) {
int now=++len;tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;tr[now].c=0;tr[now].n=r-l+1;tr[now].lazy=0;
if(l<r) {int mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid+1,r);}
}
void update(int now) {
int lc=tr[now].lc,rc=tr[now].rc;
tr[now].lazy=0;tr[lc].lazy^=1;tr[rc].lazy^=1;
tr[lc].c=tr[lc].n-tr[lc].c;tr[rc].c=tr[rc].n-tr[rc].c;
}
void change(int now,int l,int r) {
if(tr[now].lazy)update(now);
if(tr[now].l==l&&tr[now].r==r) {tr[now].c=(tr[now].n-tr[now].c);tr[now].lazy^=1;return ;}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)change(lc,l,r);else if(l>mid)change(rc,l,r);
else {change(lc,l,mid);change(rc,mid+1,r);}
tr[now].c=tr[lc].c+tr[rc].c;
}
int find_sum(int now,int l,int r) {
if(tr[now].lazy)update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_sum(lc,l,r);else if(l>mid)return find_sum(rc,l,r);
else return find_sum(lc,l,mid)+find_sum(rc,mid+1,r);
}
int main() {
int n,m;scanf("%d%d",&n,&m);len=0;bt(1,n);
for(int i=1;i<=m;i++) {
int t,x,y;scanf("%d%d%d",&t,&x,&y);
if(x>y)swap(x,y);
if(t==0)change(1,x,y);
else printf("%d\n",find_sum(1,x,y));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: