首页 > 其他分享 >洛谷题单指南-线段树-P3870 [TJOI2009] 开关

洛谷题单指南-线段树-P3870 [TJOI2009] 开关

时间:2024-11-27 16:37:53浏览次数:9  
标签:stat int 洛谷题 个数 tr 异或 P3870 区间 TJOI2009

原题链接:https://www.luogu.com.cn/problem/P3870

题意解读:有n个数的序列,初始都是0,支持两种操作:将区间[l,r]内所有数异或1,求区间[l,r]内1个个数,输出所有求区间1的个数操作的结果。

解题思路:

灯的开关可以用0,1表示,改变灯的状态可以用异或操作,统计多少灯是开的就是计算1的个数,因此该题很容易进行转化。

现在要分析两个关键点:

1、计算区间1的个数是否具有可合并性?

显然,对于mid=(l+r)/2,区间[l,r]中1的个数 = [l,mid]中1的个数 + [mid+1,r]中1的个数,具有可合并行。

2、元素进行异或1是否具有可加性?

对一个开关tag,按一下异或1,状态是tag ^= 1,再按一下再异或1,状态同样tag ^= 1,具有可加性。

因此,此题可以用线段树解决,区间1的个数可以作为树节点的信息,当前开关的状态可以作为树节点的懒标记。

当更新节点并添加懒标记时:

void addtag(int u, int stat)
{
    //对区间所有数异或1,则区间1的个数变成区间0的个数
    tr[u].sum = (tr[u].r - tr[u].l + 1) - tr[u].sum;
    //懒标记异或上1
    tr[u].stat ^= stat;
}

100分代码:

 

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;

struct Node
{
    int l, r;
    int sum; //区间[l,r]中1的个数
    int stat; //懒标记,表示所有子节点的值都要异或stat
} tr[N * 4];
int n, m;

void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if(l == r) tr[u].sum = 0, tr[u].stat = 0;
    else 
    {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void addtag(int u, int stat)
{
    tr[u].sum = tr[u].r - tr[u].l + 1 - tr[u].sum;
    tr[u].stat ^= stat;
}

void pushdown(int u)
{
    if(tr[u].stat)
    {
        addtag(u << 1, tr[u].stat);
        addtag(u << 1 | 1, tr[u].stat);
        tr[u].stat = 0;
    }
}

int query(int u, int l, int r)
{
    if(tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
    else if(tr[u].l > r || tr[u].r < l) return 0;
    else
    {
        pushdown(u);
        return query(u << 1, l, r) + query(u << 1 | 1, l, r);
    }
}

void update(int u, int l, int r)
{
    if(tr[u].l >= l && tr[u].r <= r) addtag(u, 1);
    else if(tr[u].l > r || tr[u].r < l) return;
    else
    {
        pushdown(u);
        update(u << 1, l, r);
        update(u << 1 | 1, l, r);
        pushup(u);
    }
}

int main()
{
    cin >> n >> m;
    build(1, 1, n);
    int op, x, y;
    while(m--)
    {
        cin >> op >> x >> y;
        if(op == 0) update(1, x, y);
        else cout << query(1, x, y) << endl;
    }
}

 

标签:stat,int,洛谷题,个数,tr,异或,P3870,区间,TJOI2009
From: https://www.cnblogs.com/jcwy/p/18572314

相关文章

  • 洛谷题单 / P5713 【深基3.例5】洛谷团队系统
    点击后神威传送至题目<<<作者最近换封面了,帅不帅题目描述在洛谷上使用团队系统非常方便的添加自己的题目。如果在自己的电脑上配置题目和测试数据,每题需要花费时间 5 分钟;而在洛谷团队中上传私有题目,每题只需要花费 3分钟,但是上传题目之前还需要一次性花费 11 分钟创建......
  • 洛谷题单指南-字符串-P2922 [USACO08DEC] Secret Message G
    原题链接:https://www.luogu.com.cn/problem/P2922题意解读:已知M个01串,给出N个01串,对于N个串的每一个,求在M个串中有多少与其有公共前缀,且前缀长度是两个串中较小者。解题思路:用Trie树存储M个01串,用cnt1[]记录某个节点结束的01串个数,cnt2[]记录经过某个节点的01串的数量对于N个0......
  • 洛谷题单指南-字符串-P2375 [NOI2014] 动物园
    原题链接:https://www.luogu.com.cn/problem/P2375题意解读:计算字符串所有子串的不重叠相同前后缀数量。解题思路:1、KMP+暴力通过Next数组,可以计算所有子串相同前后缀的数量然后枚举Next数组,通过回跳Next[j]、Next[Next[j]-1]、Next[Next[Next[j]-1]-1]......来统计长度小于......
  • 洛谷题单指南-分治与倍增-P6648 [CCC2019] Triangle: The Data Structure
    原题链接:https://www.luogu.com.cn/problem/P6648题意解读:在一个n行的数字三角形中,求所有边长为k的正三角形最大值之和。解题思路:1、枚举法枚举每一个边长为k的三角形,在其中求max,然后累加,n最多3000,时间复杂度是n^4,显然超时。2、倍增和ST思想此题非常类似于RMQ问题,也就是求区......
  • 洛谷题单指南-分治与倍增-P3517 [POI2011] WYK-Plot
    原题链接:https://www.luogu.com.cn/problem/P3517题意解读:有n个连续的点p1,p2,...,pn,将这n个点分成不超过m堆,每堆点连续,每一堆都缩成一个点qi,要使得原来的点p1~ps距离qi的最大值最小(最相似),求这个相似度,并计算一共分成几堆,以及每堆缩到的点qi的坐标。解题思路:要使得若干点缩到一......
  • 洛谷题单指南-分治与倍增-P7167 [eJOI2020 Day1] Fountain
    原题链接:https://www.luogu.com.cn/problem/P7167题意解读:从喷泉任意一个圆盘倒水,水流经的圆盘直径必须递增,水最后流到哪个圆盘。解题思路:1、枚举法有30%的数据范围在N<=1000,Q<=1000,因此枚举也可以得到30分。可以通过单调栈预计算每个圆盘后面第一个直径更大的圆盘位置Next[......
  • 洛谷题单指南-分治与倍增-P1226 【模板】快速幂
    原题链接:https://www.luogu.com.cn/problem/P1226题意解读:快速幂模版题。解题思路:1、分治法要计算a^b,可以对b分情况讨论:如果b是偶数,即b=2t,a^b=a^t*a^t如果b是奇数,即b=2t+1,a^b=a*a^t*a^t很容易用递归实现100分代码:#include<bits/stdc++.h>usingnamespa......
  • 洛谷题单指南-分治与倍增-P1966 [NOIP2013 提高组] 火柴排队
    原题链接:https://www.luogu.com.cn/problem/P1966题意解读:计算两个序列∑(ai​−bi​)^2的最小值,对10^8-3取模。解题思路:1、贪心思路要使得两个序列对应位置元素之差的平方和最小,必须满足两个序列相对排序是一致的,什么意思?设a序列有两个元素:a1,a2,b序列有两个元素b1,b2当a1<a2,b......
  • 洛谷题单指南-分治与倍增-P1908 逆序对
    原题链接:https://www.luogu.com.cn/problem/P1908题意解读:求序列逆序对数。解题思路:1、暴力法对于每一个数,寻找后面有多少数比其小,或者采用冒泡排序,交换的次数即逆序对的个数,复杂度为O(n^2)2、归并排序法在归并排序过程中,会进行有序序列的合并,设两部分连续的有序序列为a[s1,......
  • 洛谷题单指南-常见优化技巧-P2880 [USACO07JAN] Balanced Lineup G
    原题链接:https://www.luogu.com.cn/problem/P2880题意解读:在若干个不定长区间里,求区间最大值与最小值之差解题思路:对于区间求最值,通常有几种方式:1、暴力法,通过枚举所有的区间来计算区间最值2、单调队列,针对区间长度固定的情况3、ST表,针对区间长度不固定且元素不会发生改变的......