zoukankan      html  css  js  c++  java
  • 洛谷 P2846 光开关

    https://www.luogu.org/problemnew/show/P2846

    好多题解用线段树来写,然而分块不是更简单好些吗?

    一个数组use记录这一块进行了多少次开关操作,两边单独计算,注意每次更新两边是也要维护这一块。

    查询两边暴力加减,块内循环枚举。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n,m,k,bl[100006],f[100006],a[100006],use[100006];
    void Xor(int l,int r)
    {
        for(int i=l;i<=min(bl[l]*k,r);i++)f[bl[i]]+=a[i]^use[bl[i]]?-1:1,a[i]^=1;
        if(bl[l]!=bl[r])for(int i=(bl[r]-1)*k+1;i<=r;i++)f[bl[i]]+=a[i]^use[bl[i]]?-1:1,a[i]^=1;
        for(int i=bl[l]+1;i<bl[r];i++)use[i]^=1,f[i]=k-f[i];
    }
    int query(int l,int r)
    {
        int ans=0;
        for(int i=l;i<=min(r,bl[l]*k);i++)ans+=a[i]^use[bl[i]];
        if(bl[l]!=bl[r])for(int i=(bl[r]-1)*k+1;i<=r;i++)ans+=a[i]^use[bl[i]];
        for(int i=bl[l]+1;i<bl[r];i++)ans+=f[i];
        return ans;
    }
    int main()
    {
        int x,y,z;
        scanf("%d%d",&n,&m);
        k=sqrt(n);
        for(int i=1;i<=n;i++)bl[i]=(i-1)/k+1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&z,&x,&y);
            if(z==0)Xor(x,y);
            else printf("%d
    ",query(x,y));
        }
    }
  • 相关阅读:
    【leetcode】N叉树的前序遍历
    【leetcode】第 N 个泰波那契数
    【leetcode】下一个更大元素 I
    【leetcode】Nim 游戏
    【leetcode】非递减数列
    053-208
    053-211
    053-56
    053-53
    053-236
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9674946.html
Copyright © 2011-2022 走看看