硬幣翻轉問題,區間操做

描述:

  給定n個硬幣,編號爲0, 1, 2, ......, n-1,都爲反面朝上(即都爲0)。有m次操做,每次將a, b區間內的硬幣翻轉,請輸出翻轉後的硬幣排列。ios

輸入:

5 2
1 2
2 4數組

輸出:

10110spa


解析:

  對於該題,最簡單的作法是模擬,即創建數組s[n],初始化爲0,而後每次將[a, b]上的數字+1,最後順序輸出。若是s[i]爲偶數,則爲0面朝上,不然爲1面朝上。這種作法的修改的時間複雜度爲O(m*n),輸出爲O(n),當m和n都比較大的時候代價難以承受。code

  顯然題目要求是對區間進行操做,因此天然而然地想到了樹狀數組或線段樹。通過模擬方法的分析後,發現操做爲區間修改,求單點的值,用樹狀數組或線段樹均可以實現。因爲線段樹的代碼比較複雜,因此選擇樹狀數組。ci

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define lowbit(a) (a&(-a))
using namespace std;
int n,m;
int s[100100];

void add(int x,int c)
{
    for(int i=x;i>0;i-=lowbit(i)) s[i]+=c;
}

int sum(int x)
{
    int r=0;
    for(int i=x;i<=n;i+=lowbit(i)) r+=s[i];
    return r;
}

int main()
{
    memset(s,0,sizeof(s));
    cin>>n>>m;
    int a,b;
    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        add(a-1,-1);
        add(b,1);
    }
    for(int i=1;i<=n;i++)
    {
        int c=sum(i);
        cout<<(c&1);
    }
    return 0;
}
相關文章
相關標籤/搜索