p2572 [scoi2010]序列操作
這道題題解已經很多了
但是我還是想寫一篇
紀念 調三天**
思路 很簡單
struct node
tree[maxn << 2];
len:長度
sum:1的個數
lazy:把[a, b]區間內的所有數全變成0/1標記
rev:反轉標記
lsum[1/0]:記錄從左邊開始的最長連續1/0的個數
rsum[1/0]:記錄從右邊開始的最長連續1/0的個數
maxl[1/0]:記錄區間內最長連續1/0的個數
然後 就正常的線段樹操作了
主要是除錯
來說一些技巧
\(pushdown\)時 要麼左區間,要麼右區間
可以考慮 兩次\(pushdown\)
每次傳 現在區間標號 修改區間標號 修改區間長度
pushdown(k,k << 1,mid - l + 1);
pushdown(k,k << 1 | 1,r - mid);
r - mid !!不要+1!!
類似的
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,0);
修改lsum[0],rsum[0],maxl[0]
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,1);
修改lsum[1],rsum[1],maxl[1]
#include #include #include #include #include using namespace std;
#define reg register int
#define isdigit(x) ('0' <= x&&x <= '9')
templateinline t read(t type)
while(isdigit(a))
return x * f;
}const int maxn = 100010;
struct segment_tree
tree[maxn << 2];
void update(int k,int k1,int k2,int lenl,int lenr,int x)
void build(int k,int l,int r)
int mid = l + r >> 1;
tree[k].lazy = -1,tree[k].rev = 0;
build(k << 1,l,mid);
build(k << 1 | 1,mid + 1,r);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,0);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,1);
} void pushdown(int k,int k1,int len)
if(tree[k].rev)
}void change(int k,int l,int r,int l,int r,int x)
int mid = l + r >> 1;
pushdown(k,k << 1,mid - l + 1);
pushdown(k,k << 1 | 1,r - mid);
tree[k].lazy = -1,tree[k].rev = 0;
if(l <= mid) change(k << 1,l,mid,l,r,x);
if(mid < r) change(k << 1 | 1,mid + 1,r,l,r,x);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,0);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,1);
} void inverse(int k,int l,int r,int l,int r)
int mid = l + r >> 1;
pushdown(k,k << 1,mid - l + 1);
pushdown(k,k << 1 | 1,r - mid);
tree[k].lazy = -1,tree[k].rev = 0;
if(l <= mid) inverse(k << 1,l,mid,l,r);
if(mid < r) inverse(k << 1 | 1,mid + 1,r,l,r);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,0);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,1);
} int query(int k,int l,int r,int l,int r)
node sum(int k,int l,int r,int l,int r)
int mid = l + r >> 1;
pushdown(k,k << 1,mid - l + 1);
pushdown(k,k << 1 | 1,r - mid);
tree[k].lazy = -1,tree[k].rev = 0;
node k1[2];
memset(k1,0,sizeof(k1));
if(l <= mid) k1[0] = sum(k << 1,l,mid,l,r);
if(mid < r) k1[1] = sum(k << 1 | 1,mid + 1,r,l,r);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,0);
update(k,k << 1,k << 1 | 1,mid - l + 1,r - mid,1);
node k3;
k3.maxl[1] = max(k1[0].maxl[1],max(k1[1].maxl[1],k1[0].rsum[1] + k1[1].lsum[1]));
k3.lsum[1] = k1[0].lsum[1];
if(k1[0].lsum[1] == k1[0].len) k3.lsum[1] += k1[1].lsum[1];
k3.rsum[1] = k1[1].rsum[1];
if(k1[1].rsum[1] == k1[1].len) k3.rsum[1] += k1[0].rsum[1];
k3.len = k1[0].len + k1[1].len;
//不要忘了算len 這行沒寫 只會wa兩個點
return k3;
}}t;
int main()
} return 0;
}
這種毒瘤資料結構題
先靜態查錯
再對拍然後求助
或者直接求助
幫助工具
如果還沒調出來 可以嘗試以下方式
小蒟蒻皮皮魚 提供的對拍程式
#includeusing namespace std;
int main()
}
ljc00118 提供的
資料生成程式
RMQ 線段樹複習
首先是rmq include include includeusing namespace std const int maxn 50000 100 int dmax maxn 20 int dmin maxn 20 void initmax int n,int d 初始化最大值查詢 遞迴建立線段樹...
複習 線段樹基礎
大部分題目是純模板,只寫一下 山海經 題意 查詢區間最大欄位和 不帶修 考慮區間最大子段和由 貢獻得到,可能是lson的ans,rson的ans,也可以是lson與rson拼接而成 只需要抽象出加法 push up 操作,就很好理解了 網上題解太麻煩,需要各種分類討論,容易寫掛 所以直接抽象出加法即...
線段樹合併複習筆記
線段樹合併和主席樹不同的是。主席樹的節點還要依賴之前的樹結構。而線段樹合併是若干個分離的線段樹合併起來,在建立節點的時候有些不同。按照dfs的順序處理。顯然乙個子樹內的交換只會影響該子樹,所以可以貪心得對於每個子樹決定是否交換。算到葉子節點的時候新建一顆log loglo g個節點的權值線段樹。合併...