zoukankan      html  css  js  c++  java
  • 洛谷 P3870 [TJOI2009]开关

    题意简述

    有n盏灯,默认为关,有两个操作:
    1.改变l~r的灯的状态(把开着的灯关上,关着的灯打开)
    2.查询l~r开着的灯的数量

    题解思路

    维护一个线段树,支持区间修改,区间查询
    懒标记每次^1

    代码

    #include <cstdio>
    using namespace std;
    int n, m, opt, x, y;
    int a[400010], la[400010];
    void push_up(int x)
    {
    	a[x] = a[x << 1] + a[x << 1 | 1];
    }
    void push_down(int x, int len)
    {
    	a[x << 1] = (len - (len >> 1)) - a[x << 1];
    	a[x << 1 | 1] = (len >> 1) - a[x << 1 | 1];
    	la[x << 1] ^= 1;
    	la[x << 1 | 1] ^= 1;
    	la[x] = 0;
    }
    void change(int x, int l, int r, int l1, int r1)
    {
    	if (l1 <= l && r <= r1)
    	{
    		a[x] = r - l + 1 - a[x];
    		la[x] ^= 1;
    		return;
    	}
    	if (la[x]) push_down(x, r - l + 1);
    	int mid = l + r >> 1;
    	if (l1 <= mid) change(x << 1, l, mid, l1, r1);
    	if (r1 >  mid) change(x << 1 | 1, mid + 1, r, l1, r1);
    	push_up(x); 
    }
    int query(int x, int l, int r, int l1, int r1, int ans = 0)
    {
    	if (l1 <= l && r <= r1)	return a[x];
    	if (la[x]) push_down(x, r - l + 1);
    	int mid = l + r >> 1;
    	if (l1 <= mid) ans += query(x << 1, l, mid, l1, r1);
    	if (r1 >  mid) ans += query(x << 1 | 1, mid + 1, r, l1, r1);
    	return ans;
    }
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (register int i = 1; i <= m; ++i)
    	{
    		scanf("%d", &opt);
    		if (!opt)
    		{
    			scanf("%d%d", &x, &y);
    			change(1, 1, n, x, y);
    		}
    		else
    		{
    			scanf("%d%d", &x, &y);
    			printf("%d
    ", query(1, 1, n, x, y));
    		}
    	}
    }
    
  • 相关阅读:
    [BZOJ4034][HAOI2015]树上操作
    [BZOJ1030][JSOI2007]文本生成器
    [BZOJ2763][JLOI2011]飞行路线
    [POJ3667]Hotel
    [codevs1566]染色
    [codevs2460]树的统计
    [BZOJ2667][cqoi2012][kcoj]模拟工厂
    [NOI2009][codevs1846]KCOJ0191]植物大战僵尸
    [POJ1087]A Plug for UNIX
    Educational Round 66 题解
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9477707.html
Copyright © 2011-2022 走看看