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);
    }
}

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);
        }
    }
}

时间: 2024-10-13 11:00:45

CODEVS线段树小结的相关文章

线段树小结

线段树基本概念 线段树/区间树是一种非常常用的对区间数据进行操作的数据结构.     线段树是一棵二叉树(但不一定是完全二叉树!),它的每个节点均代表一个区间,且父节点代表的区间为左右子节点代表的区间之和.特别的,根节点代表的区间为所有节点代表区间之和,各个叶节点代表区间为单个点(即长度为1的区间). 线段树结构 树中的每一个结点表示了一个区间[a,b]. a,b通常是整数.每一个叶子节点表示了一个单位区间(长度为1).对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a,(a+b

线段树 模板

以codevs 线段树练习1.2为例 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int n,m; 6 struct node { 7 int l,r,sum; 8 }tree[100010*4]; 9 void built(int l,int r,int k) 10 { 11 tree[k].l=l;tree[k].r=r; 12 if(l==

线段树入门小结

QUE:线段树? 称谓: 从刘汝佳的书中得知,"这种数据结构在学术界没有统一的术语,但线段树是最常见的叫法.其他叫法包括区间树(interval tree).范围树(range tree)等,但这些属于在特定的场合(如计算几何)中有着特殊的意义".怎么叫看读者的心情,以下统一用线段树称呼. 先来作一些了解: 线段树是一棵二叉树,它的左右儿子也都是一棵线段树.(定义) 线段树也叫区间树,为什么叫它区间树呢?因为线段树是一种基于区间的数据结构. 线段树的每个节点代表一个区间 [L,R],其

[Codevs] 1080 线段树练习

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

【树状数组区间修改区间求和】codevs 1082 线段树练习 3

http://codevs.cn/problem/1082/ [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=2e5+2; 5 int n; 6 ll a[maxn]; 7 ll c1[maxn]; 8 ll c2[maxn]; 9 int lowbit(int x) 10 { 11 return x&-x; 12 } 13 void add(l

1080 线段树练习 (codevs)

http://codevs.cn/problem/1080/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Des

线段树练习 codevs 1080

/* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Des

线段树--codevs 1690 开关灯

codevs 1690 开关灯 USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input

CODEVS 1081 线段树练习 2 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://codevs.cn/problem/1081/ 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果