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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanks_o/article/details/79115023

题目传送门
…..

解法:
裸线段树。。
打个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;
}
展开阅读全文

没有更多推荐了,返回首页