1. 程式人生 > >hdu-3397 Sequence operation 線段樹多種標記

hdu-3397 Sequence operation 線段樹多種標記

std tac int inf for alt http blank sizeof

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=3397

題目大意:

0 a b表示a-b區間置為0

1 a b表示a-b區間置為1

2 a b表示a-b區間中的0變成1,1變成0

3 a b表示a-b區間中的1的數目

4 a b表示a-b區間中最長連續1的長度

解題思路:

線段樹多種標記。

需要處理的東西比較多:

技術分享圖片

做題的時候發現一個問題:

我的宏定義Max不可以用於函數,尤其是遞歸函數,這樣會使得同一函數重復調用好幾遍,遞歸函數的話更會超時。

  1 #include<bits/stdc++.h>
  2 #define IOS ios::sync_with_stdio(false);//
不可再使用scanf printf 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用於函數,會超時 4 #define Min(a, b) ((a) < (b) ? (a) : (b)) 5 #define Mem(a) memset(a, 0, sizeof(a)) 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1)) 7 #define MID(l, r) ((l) + ((r) - (l)) / 2) 8 #define lson ((o)<<1) 9
#define rson ((o)<<1|1) 10 #pragma comment(linker, "/STACK:102400000,102400000")//棧外掛 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<0||ch>9){if (ch==-) f=-1;ch=getchar();} 16 while (ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
17 return x*f; 18 } 19 20 typedef long long ll; 21 const int maxn = 100000 + 10; 22 const int MOD = 1000000007;//const引用更快,宏定義也更快 23 24 struct node 25 { 26 int l, r;//左右區間 27 int ls0, rs0, ms0;//左連續的0,右連續的0,區間最大連續的0 28 int ls1, rs1, ms1;//左連續的1,右連續的1,區間最大連續的1 29 int sum0, sum1;//區間0 1數目 30 int lazy, Xor;//懶惰標記和異或標記 31 }tree[maxn << 2]; 32 int a[maxn]; 33 void pushup(int o) 34 { 35 if(tree[o].l == tree[o].r)return;//葉子節點直接返回 36 //根據子節點的信息,更新父節點信息 37 38 //更新0: 39 int lc = lson, rc = rson; 40 tree[o].ls0 = tree[lc].ls0; 41 tree[o].rs0 = tree[rc].rs0; 42 if(tree[lc].ls0 == tree[lc].r - tree[lc].l + 1) 43 tree[o].ls0 += tree[rc].ls0;//左節點左連續的0為區間長度 那麽根節點左連續的0需要再加上右節點左連續的0 44 if(tree[rc].rs0 == tree[rc].r - tree[rc].l + 1) 45 tree[o].rs0 += tree[lc].rs0; 46 tree[o].ms0 = Max(Max(tree[lc].ms0, tree[rc].ms0), tree[lc].rs0 + tree[rc].ls0);//最大連續0 = Max(左節點最大連續0, 右節點最大連續0,中間最大連續0) 47 tree[o].sum0 = tree[lc].sum0 + tree[rc].sum0; 48 //更新1 49 tree[o].ls1 = tree[lc].ls1; 50 tree[o].rs1 = tree[rc].rs1; 51 if(tree[lc].ls1 == tree[lc].r - tree[lc].l + 1) 52 tree[o].ls1 += tree[rc].ls1;//左節點左連續的0為區間長度 那麽根節點左連續的0需要再加上右節點左連續的0 53 if(tree[rc].rs1 == tree[rc].r - tree[rc].l + 1) 54 tree[o].rs1 += tree[lc].rs1; 55 tree[o].ms1 = Max(Max(tree[lc].ms1, tree[rc].ms1), tree[lc].rs1 + tree[rc].ls1);//最大連續0 = Max(左節點最大連續0, 右節點最大連續0,中間最大連續0) 56 tree[o].sum1 = tree[lc].sum1 + tree[rc].sum1; 57 } 58 void XOR(int o) 59 { 60 swap(tree[o].ls0, tree[o].ls1); 61 swap(tree[o].rs0, tree[o].rs1); 62 swap(tree[o].ms0, tree[o].ms1); 63 swap(tree[o].sum0, tree[o].sum1); 64 } 65 void pushdown(int o)//標記下傳 66 { 67 if(tree[o].l == tree[o].r)return; 68 if(tree[o].lazy != -1)//區間覆蓋0或者1 69 { 70 int lc = lson, rc = rson, len = tree[o].r - tree[o].l + 1; 71 tree[lc].lazy = tree[rc].lazy = tree[o].lazy; 72 tree[lc].Xor = tree[rc].Xor = 0; 73 74 //左節點長度為(len+1) / 2 右節點長度為len/2 75 // 76 tree[lc].ls0 = tree[lc].rs0 = tree[lc].ms0 = tree[o].lazy ? 0 : (len + 1) / 2; 77 tree[lc].ls1 = tree[lc].rs1 = tree[lc].ms1 = tree[o].lazy ? (len + 1) / 2 : 0; 78 tree[lc].sum0 = tree[o].lazy ? 0 : (len + 1) / 2; 79 tree[lc].sum1 = tree[o].lazy ? (len + 1) / 2 : 0; 80 // 81 tree[rc].ls0 = tree[rc].rs0 = tree[rc].ms0 = tree[o].lazy ? 0 : (len) / 2; 82 tree[rc].ls1 = tree[rc].rs1 = tree[rc].ms1 = tree[o].lazy ? (len) / 2 : 0; 83 tree[rc].sum0 = tree[o].lazy ? 0 : (len) / 2; 84 tree[rc].sum1 = tree[o].lazy ? (len) / 2 : 0; 85 86 tree[o].lazy = -1;//清除標記 87 } 88 if(tree[o].Xor) 89 { 90 tree[o].Xor = 0; 91 tree[lson].Xor ^= 1; 92 tree[rson].Xor ^= 1; 93 XOR(lson), XOR(rson); 94 } 95 } 96 void build(int o, int l, int r) 97 { 98 tree[o].l = l, tree[o].r = r, tree[o].lazy = -1, tree[o].Xor = 0; 99 if(l == r) 100 { 101 tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = (a[l] == 0); 102 tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = (a[l] == 1); 103 tree[o].sum1 = (a[l] == 1); 104 tree[o].sum0 = (a[l] == 0); 105 return; 106 } 107 int m = MID(l, r); 108 build(lson, l, m); 109 build(rson, m + 1, r); 110 pushup(o); 111 } 112 int flag;//標記類型 113 int ql, qr; 114 void update(int o) 115 { 116 pushdown(o); 117 if(ql <= tree[o].l && qr >= tree[o].r) 118 { 119 if(flag == 2) 120 { 121 tree[o].Xor = 1; 122 XOR(o); 123 } 124 else 125 { 126 int len = tree[o].r - tree[o].l + 1; 127 tree[o].lazy = flag; 128 tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = flag ? 0 : len; 129 tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = flag ? len : 0; 130 tree[o].sum0 = flag ? 0 : len; 131 tree[o].sum1 = flag ? len : 0; 132 } 133 } 134 else 135 { 136 int m = MID(tree[o].l, tree[o].r); 137 if(ql <= m)update(lson); 138 if(qr > m)update(rson); 139 pushup(o); 140 } 141 } 142 143 int query(int o) 144 { 145 pushdown(o); 146 if(ql <= tree[o].l && qr >= tree[o].r) 147 { 148 if(flag == 3)return tree[o].sum1; 149 else return tree[o].ms1; 150 } 151 else 152 { 153 if(qr <= tree[lson].r)return query(lson); 154 if(ql >= tree[rson].l)return query(rson); 155 if(flag == 3)return query(lson) + query(rson); 156 int ans1 = Min(tree[lson].rs1, tree[lson].r - ql + 1) + Min(tree[rson].ls1, qr - tree[rson].l + 1); 157 int ans2 = max(query(lson), query(rson));//用宏定義會超時,因為一直在遞歸 158 return Max(ans1, ans2); 159 } 160 } 161 162 int main() 163 { 164 int T; 165 scanf("%d", &T); 166 while(T--) 167 { 168 int n, m; 169 scanf("%d%d", &n, &m); 170 for(int i = 1; i <= n; i++)scanf("%d", &a[i]); 171 build(1, 1, n); 172 while(m--) 173 { 174 scanf("%d%d%d", &flag, &ql, &qr); 175 ql++, qr++; 176 if(flag < 3)update(1); 177 else printf("%d\n", query(1)); 178 } 179 } 180 return 0; 181 }

hdu-3397 Sequence operation 線段樹多種標記