首页 > 代码库 > CODEVS线段树小结

CODEVS线段树小结

CODEVS1369 xth 砍树

题目大意:区间查询和,单点修改区间中点。

思路:比较简单的线段树,可是在double和float上栽了跟头,以后统一用double,输出printf里面用f,不要用llf(我zuo)。

#include<iostream>#include<cstdio>using namespace std;int tree[800000]={0},a[200001]={0};void build(int i,int l,int r){    int mid;    if (l==r)     {        tree[i]=a[l];        return;    }    mid=(l+r)/2;    build(i*2,l,mid);    build(i*2+1,mid+1,r);    tree[i]=tree[i*2]+tree[i*2+1];}int work(int i,int l,int r,int aa,int b){    int mid,sum=0;    if (aa<=l&&r<=b)        return tree[i];    mid=(l+r)/2;    if (aa<=mid) sum+=work(i*2,l,mid,aa,b);    if (b>mid)  sum+=work(i*2+1,mid+1,r,aa,b);    return sum;}void insert(int i,int l,int r,int aa){    int mid;    if (l==r&&l==aa)    {        tree[i]=0;        return;    }    mid=(l+r)/2;    if (aa<=mid) insert(i*2,l,mid,aa);    else insert(i*2+1,mid+1,r,aa);    tree[i]=tree[i*2]+tree[i*2+1];}int main(){    int n,m,i,j,l,r,sum;    double ans;    scanf("%d",&n);    for (i=1;i<=n;++i)      scanf("%d",&a[i]);    build(1,1,n);    scanf("%d",&m);    for (i=1;i<=m;++i)    {        scanf("%d%d",&l,&r);        sum=work(1,1,n,l,r);        insert(1,1,n,(l+r)/2);        ans=sum*3.14;        printf("%0.2f\n",ans);    }}
View Code

 

CODEVS1690 开关灯

题目大意:区间置反,区间查询。

思路:用delta数组表示区间置反的状态,这里就有出现了一个小问题,对于delta数组的思想不够了解,认识不够深入,其实delta数组表示的是这个节点的状态的累加,在每次pushdown的时候会将这个状态推至孩子,自己的状态清为0(大多数),所以在这个程序的paint中,delta[i]=!delta[i],而不是delta[i]=0。以后应该好好理解最基本的东西,注意细节。

#include<iostream>#include<cstdio>using namespace std;int tree[400000]={0},delta[400000]={0};void paint(int i,int l,int r){    tree[i]=r-l+1-tree[i];    delta[i]=!delta[i];}void pushdown(int i,int l,int r){    int mid;    mid=(l+r)/2;    paint(i*2,l,mid);    paint(i*2+1,mid+1,r);    delta[i]=0;}void insert(int i,int l,int r,int a,int b){    int mid;    if (a<=l&&r<=b)    {        paint(i,l,r);        return;    }    if (delta[i]==1) pushdown(i,l,r);    mid=(l+r)/2;    if (a<=mid) insert(i*2,l,mid,a,b);    if (b>mid) insert(i*2+1,mid+1,r,a,b);    tree[i]=tree[i*2]+tree[i*2+1];}int work(int i,int l,int r,int a,int b){    int mid,sum=0;    if (a<=l&&r<=b)        return tree[i];    if (delta[i]==1)         pushdown(i,l,r);    mid=(l+r)/2;    if (a<=mid) sum+=work(i*2,l,mid,a,b);    if (b>mid) sum+=work(i*2+1,mid+1,r,a,b);    return sum;}int main(){    int n,m,i,j,l,r,ans;    scanf("%d%d",&n,&m);    for (i=1;i<=m;++i)    {        scanf("%d%d%d",&j,&l,&r);        if (j==0)          insert(1,1,n,l,r);        else         {            ans=work(1,1,n,l,r);            printf("%d\n",ans);        }    }}
View Code

 

CODEVS线段树小结