Sequence operation HDU - 3397 (線段樹區(qū)間合并)

題目來源:Sequence operation

題意

給你一個(gè)長度為n的01串移层,現(xiàn)在有m次操作

0 a b表示把區(qū)間[a, b]全部變?yōu)?

1 a b表示把區(qū)間[a, b]全部變?yōu)?

2 a b表示把區(qū)間[a, b]翻轉(zhuǎn)论熙,0變1,1變0

3 a b輸出區(qū)間[a, b]中1的個(gè)數(shù)

4 a b輸出區(qū)間[a, b]中最長連續(xù)的1的長度

思路

用線段樹維護(hù)區(qū)間從左、右開始數(shù)0和1的最大長度万哪,區(qū)間內(nèi)01的最大長度帘撰,區(qū)間內(nèi)1的數(shù)量和區(qū)間是否翻轉(zhuǎn)

由于一個(gè)區(qū)間翻轉(zhuǎn)偶數(shù)次后的結(jié)果和初始結(jié)果一致政钟,所以如果區(qū)間在已有翻轉(zhuǎn)標(biāo)記的情況下再增添一個(gè)翻轉(zhuǎn)標(biāo)記則無需翻轉(zhuǎn)

注意此題需要將pushdown在查詢和更新的最開始處下推蜈敢,不然會(huì)有標(biāo)記推不下去。

代碼

#include <cstdio>
#include <cstring>
#include <iostream>
const int N = 100010;
int a[N];
inline int max(int x, int y) { return x > y ? x : y; }
inline int min(int x, int y) { return x > y ? y : x; }
namespace SEG
{
    struct Tag
    {
        int lzero, rzero, mzero;
        int lone, rone, mone;
        int sum;
        int lazy, x_or;
    } c[N << 2];
    inline void pushDown(int k, int l, int r)
    {
        if (l == r)    return;
        int mid = (l + r) >> 1;
        if (c[k].lazy != -1)
        {
            c[k << 1].lazy = c[k << 1 | 1].lazy = c[k].lazy;
            c[k << 1].x_or = c[k << 1 | 1].x_or = 0;
            if (c[k].lazy == 0)
            {
                c[k << 1].lzero = c[k << 1].rzero = c[k << 1].mzero = mid - l + 1;
                c[k << 1].sum = c[k << 1].lone = c[k << 1].rone = c[k << 1].mone = 0;
                c[k << 1 | 1].lzero = c[k << 1 | 1].rzero = c[k << 1 | 1].mzero = r - mid;
                c[k << 1 | 1].sum = c[k << 1 | 1].lone = c[k << 1 | 1].rone = c[k << 1 | 1].mone = 0;
            }
            else if (c[k].lazy == 1)
            {
                c[k << 1].lzero = c[k << 1].rzero = c[k << 1].mzero = 0;
                c[k << 1].sum = c[k << 1].lone = c[k << 1].rone = c[k << 1].mone = mid - l + 1;
                c[k << 1 | 1].lzero = c[k << 1 | 1].rzero = c[k << 1 | 1].mzero = 0;
                c[k << 1 | 1].sum = c[k << 1 | 1].lone = c[k << 1 | 1].rone = c[k << 1 | 1].mone = r - mid;
            }
            c[k].lazy = -1;
        }
        if (c[k].x_or)
        {
            c[k << 1].x_or ^= 1;
            c[k << 1 | 1].x_or ^= 1;

            std::swap(c[k << 1].lzero, c[k << 1].lone);
            std::swap(c[k << 1].rzero, c[k << 1].rone);
            std::swap(c[k << 1].mzero, c[k << 1].mone);
            c[k << 1].sum = mid - l + 1 - c[k << 1].sum;

            std::swap(c[k << 1 | 1].lzero, c[k << 1 | 1].lone);
            std::swap(c[k << 1 | 1].rzero, c[k << 1 | 1].rone);
            std::swap(c[k << 1 | 1].mzero, c[k << 1 | 1].mone);
            c[k << 1 | 1].sum = (r - mid) - c[k << 1 | 1].sum;

            c[k].x_or = 0;
        }
    }
    inline void pushUp(int k, int l, int r)
    {
        int mid = (l + r) >> 1;

        c[k].lzero = c[k << 1].lzero;
        c[k].rzero = c[k << 1 | 1].rzero;
        if (c[k].lzero >= mid - l + 1)
            c[k].lzero += c[k << 1 | 1].lzero;
        if (c[k].rzero >= r - mid)
            c[k].rzero += c[k << 1].rzero;
        c[k].mzero = max(c[k << 1].rzero + c[k << 1 | 1].lzero, max(c[k << 1].mzero, c[k << 1 | 1].mzero));

        c[k].lone = c[k << 1].lone;
        c[k].rone = c[k << 1 | 1].rone;
        if (c[k].lone >= mid - l + 1)
            c[k].lone += c[k << 1 | 1].lone;
        if (c[k].rone >= r - mid)
            c[k].rone += c[k << 1].rone;
        c[k].mone = max(c[k << 1].rone + c[k << 1 | 1].lone, max(c[k << 1].mone, c[k << 1 | 1].mone));

        c[k].sum = c[k << 1].sum + c[k << 1 | 1].sum;
    }
    void build(int k, int l, int r)
    {
        c[k].lazy = -1;
        c[k].x_or = 0;
        if (l == r)
        {
            if (a[l] == 0)
            {
                c[k].lzero = c[k].rzero = c[k].mzero = 1;
                c[k].sum = c[k].lone = c[k].rone = c[k].mone = 0;
            }
            else if (a[l] == 1)
            {
                c[k].lzero = c[k].rzero = c[k].mzero = 0;
                c[k].sum = c[k].lone = c[k].rone = c[k].mone = 1;
            }
            return;
        }
        int mid = (l + r) >> 1;

        build(k << 1, l, mid);
        build(k << 1 | 1, mid + 1, r);

        pushUp(k, l, r);
    }
    // l, r是總區(qū)間 left, right是查詢區(qū)間
    int query_sum(int k, int l, int r, int left, int right)
    {
        pushDown(k, l, r);
        if (left <= l && r <= right)    return c[k].sum;

        int ans = 0;

        int mid = (l + r) >> 1;
        if (left <= mid)    ans += query_sum(k << 1, l, mid, left, right);
        if (mid < right)    ans += query_sum(k << 1 | 1, mid + 1, r, left, right);

        return ans;
    }
    int query_max(int k, int l, int r, int left, int right)
    {
        pushDown(k, l, r);
        if (left <= l && r <= right)    return c[k].mone;

        int ans = 0;

        int mid = (l + r) >> 1;
        if (left <= mid)    ans = max(ans, query_max(k << 1, l, mid, left, right));
        if (mid < right)    ans = max(ans, query_max(k << 1 | 1, mid + 1, r, left, right));

        return max(ans, min(c[k << 1].rone, mid - left + 1) + min(c[k << 1 | 1].lone, right - mid));
    }
    // l, r是總區(qū)間 left, right是查詢區(qū)間殴俱,k是起始節(jié)點(diǎn)編號(hào)政冻,val是更新的值
    void update(int k, int l, int r, int left, int right, int val)
    {
        pushDown(k, l, r);
        if (left <= l && r <= right)
        {
            if (val == 0)
            {
                c[k].lazy = val;
                c[k].lzero = c[k].rzero = c[k].mzero = r - l + 1;
                c[k].sum = c[k].lone = c[k].rone = c[k].mone = 0;
            }
            else if (val == 1)
            {
                c[k].lazy = val;
                c[k].lzero = c[k].rzero = c[k].mzero = 0;
                c[k].sum = c[k].lone = c[k].rone = c[k].mone = r - l + 1;
            }
            else if (val == 2)
            {
                c[k].x_or = 1;

                std::swap(c[k].lzero, c[k].lone);
                std::swap(c[k].rzero, c[k].rone);
                std::swap(c[k].mzero, c[k].mone);
                c[k].sum = (r - l + 1) - c[k].sum;
            }
            return;
        }

        int mid = (l + r) >> 1;
        if (left <= mid)    update(k << 1, l, mid, left, right, val);
        if (mid < right)    update(k << 1 | 1, mid + 1, r, left, right, val);

        pushUp(k, l, r);
    }
}
int n, m;
int main()
{
    using namespace SEG;
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i)    scanf("%d", a + i);
        memset(c, 0, sizeof(c));
        build(1, 1, n);
        int op, x, y;
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d%d%d", &op, &x, &y);
            x++; y++;
            switch (op)
            {
            case 0:
            case 1:
            case 2:
                update(1, 1, n, x, y, op);
                break;
            case 3:
                printf("%d\n", query_sum(1, 1, n, x, y));
                break;
            case 4:
                printf("%d\n", query_max(1, 1, n, x, y));
                break;
            default:
                break;
            }
        }
    }
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市线欲,隨后出現(xiàn)的幾起案子明场,更是在濱河造成了極大的恐慌,老刑警劉巖李丰,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苦锨,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逆屡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門圾旨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人魏蔗,你說我怎么就攤上這事砍的。” “怎么了莺治?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵廓鞠,是天一觀的道長。 經(jīng)常有香客問我谣旁,道長床佳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任榄审,我火速辦了婚禮砌们,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搁进。我一直安慰自己浪感,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布饼问。 她就那樣靜靜地躺著影兽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪莱革。 梳的紋絲不亂的頭發(fā)上峻堰,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音盅视,去河邊找鬼捐名。 笑死,一個(gè)胖子當(dāng)著我的面吹牛左冬,可吹牛的內(nèi)容都是我干的桐筏。 我是一名探鬼主播纸型,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼拇砰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狰腌?” 一聲冷哼從身側(cè)響起除破,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琼腔,沒想到半個(gè)月后瑰枫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年光坝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尸诽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盯另,死狀恐怖性含,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸳惯,我是刑警寧澤商蕴,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站芝发,受9級(jí)特大地震影響绪商,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辅鲸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一格郁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧独悴,春花似錦理张、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至落蝙,卻和暖如春织狐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筏勒。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國打工移迫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人管行。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓厨埋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捐顷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荡陷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 專業(yè)考題類型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項(xiàng)A選項(xiàng)B選項(xiàng)C選項(xiàng)D選項(xiàng)E選項(xiàng)F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 9,013評(píng)論 0 13
  • 1. 關(guān)于診斷X線機(jī)準(zhǔn)直器的作用,錯(cuò)誤的是()迅涮。 (6.0 分) A. 顯示照射野 B. 顯示中心線 C. 屏蔽多...
    我們村我最帥閱讀 10,585評(píng)論 0 5
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,417評(píng)論 8 265
  • 1. l have always depended on the kindness of strangers.這個(gè)...
    應(yīng)數(shù)二班張曉婷閱讀 141評(píng)論 2 0
  • 1废赞、jquery獲取元素 jquery首先頁面加載,window.onload=function(){}替換成...
    逍遙游19閱讀 327評(píng)論 0 0