天天看點

(CSU - 1770)按鈕控制彩燈實驗(CSU - 1770)按鈕控制彩燈實驗

(CSU - 1770)按鈕控制彩燈實驗

Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 344 Solved: 130

Description

應教學安排,yy又去開心的做電學實驗了。實驗的内容分外的簡單一串按鈕通過程式設計了的EEPROM可以控制一串彩燈。然而選擇了最low的一種一對一的控制模式,并很快按照實驗指導書做完實驗的yy馬上感覺到十分無趣。于是他手指在一排按鈕上無聊的滑來滑去,對應的彩燈也不斷的變化着開關。已知每一個按鈕按下會改變對應一個彩燈的狀态,如此每次yy滑動都會改變一串彩燈的狀态。現已知彩燈最初的狀态,已經yy n次無聊的滑動的起點和終點l,r。現問彩燈最終的狀态。

Input

有多組資料。

每組資料第一行,n(1<=n<=10^5)代表彩燈串長度,t(0<=t<=10^5)代表yy滑動的次數

第二行n個數(0表示滅1表示亮)給出n個彩燈的目前的狀态。

之後t行每行兩個數li,ri(1<=li<=ri<=n)代表每次滑動的區間。

Output

每組用一行輸出最終的串的狀态,格式見樣例。

Sample Input

3 2

1 0 1

1 3

2 3

Sample Output

0 0 1

思路:一種很自然的思路就是對于一次區間[l,r]可以對[1,r]操作一次,在對[1,l-1]操作一次,然後最後隻要知道每個點操作了幾次就行。這就可以用樹狀數組在nlogn時間複雜度下實作,區間跟新,單點查詢,又我下面代碼的樹狀數組的update操作是更新x<=i<=n的點,是以是先對[l,n]操作一次,在對[r+1,n]操作一次。

當然這個題目還有一種更簡單的做法:就是記錄每個點左邊有多少個區間端點,注意左端點在這個點上算,而右端點在這個點上不算。

樹狀數組方法:

#include<cstdio>
#include<cstring>
using namespace std; 

const int maxn=;
int a[maxn],c[maxn];
int n,t;

int lowbit(int x)
{
    return x&-x;
}

void update(int x,int d)
{
    for(;x<=n;x+=lowbit(x)) c[x]+=d;
}

int getsum(int x)
{
    int sum=;
    for(;x>;x-=lowbit(x)) sum+=c[x]; 
    return sum;
}
int main()
{
    while(~scanf("%d%d",&n,&t))
    {
        memset(c,,sizeof(c));
        for(int i=;i<=n;i++) scanf("%d",a+i);
        while(t--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            update(l,);
            update(r+,-);
        }
        for(int i=;i<=n;i++)
        {
            int ans=getsum(i);
            if(ans&) printf("%d",a[i]^);
            else printf("%d",a[i]);
            if(i!=n) printf(" ");
            else printf("\n");
        }
    }
    return ;
}
           

數端點數做法:

#include<cstdio>
#include<cstring>
using namespace std; 

const int maxn=;
int a[maxn],num[maxn];

int main()
{
    int n,t;
    while(~scanf("%d%d",&n,&t))
    {
        memset(num,,sizeof(num));
        for(int i=;i<=n;i++) scanf("%d",a+i);
        while(t--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            num[l]++;
            num[r+]++;
        }
        for(int i=;i<=n;i++)
        {
            num[i]+=num[i-];
            if(num[i]&) printf("%d",a[i]^);
            else printf("%d",a[i]);
            if(i!=n) printf(" ");
            else printf("\n");
        }
    }
    return ;
}