段更新里稍微复杂的应用,需要设置多个判断标志,当时比赛的时候没做出来,还是挺烦人的
题目比较烦人,考察对线段树的理解#include <cstdio> #include <iostream> #include <cmath> using namespace std; // hdu 3397 const int MAXN = 200005; #define ll (root<<1) #define rr (ll|1) #define lson l,m,ll #define rson m+1,r,rr #define mid m=(l+r)>>1 int num[MAXN]; struct node { int sum[2]; int lf[2], rt[2], mx[2]; int sn; int l, r; int len; }nd[MAXN<<2]; void solve(node & a, node & b, node & c, int wori = 0) { for (int nima = wori; nima < 2; ++nima) { a.sum[nima] = b.sum[nima] + c.sum[nima]; a.mx[nima] = max(b.mx[nima], c.mx[nima]); if (b.rt[nima] && c.lf[nima]) { int tp = b.rt[nima] + c.lf[nima]; a.mx[nima] = max(a.mx[nima], tp); if (b.lf[nima] == b.len) a.lf[nima] = tp; else a.lf[nima] = b.lf[nima]; if (c.lf[nima] == c.len) a.rt[nima] = tp; else a.rt[nima] = c.rt[nima]; } else { a.lf[nima] = b.lf[nima]; a.rt[nima] = c.rt[nima]; } } } void build (int l, int r, int root) { nd[root].sn = -1; nd[root].l = l; nd[root].r = r; nd[root].len = r-l+1; if (l == r) { if (num[l] == 1) { nd[root].sum[1] = 1; nd[root].sum[0] = 0; nd[root].lf[1] = nd[root].rt[1] = nd[root].mx[1] = 1; nd[root].lf[0] = nd[root].rt[0] = nd[root].mx[0] = 0; } else { nd[root].sum[1] = 0; nd[root].sum[0] = 1; nd[root].lf[1] = nd[root].rt[1] = nd[root].mx[1] = 0; nd[root].lf[0] = nd[root].rt[0] = nd[root].mx[0] = 1; } return; } int mid; build(lson); build(rson); solve(nd[root], nd[ll], nd[rr]); } void pushDown(int root) { if (nd[root].sn == -1) return; if (nd[root].sn == 0) { nd[ll].sum[1] = nd[rr].sum[1] = 0; nd[ll].sum[0] = nd[ll].len; nd[rr].sum[0] = nd[rr].len; nd[rr].lf[1] = nd[rr].rt[1] = nd[rr].mx[1] = nd[ll].lf[1] = nd[ll].rt[1] = nd[ll].mx[1] = 0; nd[rr].lf[0] = nd[rr].rt[0] = nd[rr].mx[0] = nd[rr].len; nd[ll].lf[0] = nd[ll].rt[0] = nd[ll].mx[0] = nd[ll].len; nd[ll].sn = nd[rr].sn = 0; } else if (nd[root].sn == 1) { nd[ll].sum[0] = nd[rr].sum[0] = 0; nd[ll].sum[1] = nd[ll].len; nd[rr].sum[1] = nd[rr].len; nd[rr].lf[0] = nd[rr].rt[0] = nd[rr].mx[0] = nd[ll].lf[0] = nd[ll].rt[0] = nd[ll].mx[0] = 0; nd[rr].lf[1] = nd[rr].rt[1] = nd[rr].mx[1] = nd[rr].len; nd[ll].lf[1] = nd[ll].rt[1] = nd[ll].mx[1] = nd[ll].len; nd[ll].sn = nd[rr].sn = 1; } else { for (int a = ll; a <= rr; ++a) { swap(nd[a].sum[0], nd[a].sum[1]); swap(nd[a].lf[0], nd[a].lf[1]); swap(nd[a].rt[0], nd[a].rt[1]); swap(nd[a].mx[0], nd[a].mx[1]); switch (nd[a].sn) { case -1: nd[a].sn = 2; break; case 0: nd[a].sn = 1; break; case 1: nd[a].sn = 0; break; case 2: nd[a].sn = -1; break; } } } nd[root].sn = -1; } void change(int x, int y, int c, int l, int r, int root) { if (nd[root].sum[c] == nd[root].len) return; if (x <= l && y>= r) { node &k = nd[root]; k.sn = c; k.sum[c] = k.len; k.sum[1-c] = 0; k.lf[c] = k.rt[c] = k.mx[c] = k.len; k.lf[1-c] = k.rt[1-c] = k.mx[1-c] = 0; return; } pushDown(root); int mid; if (x <= m) change(x, y, c, lson); if (y > m) change(x, y, c, rson); solve(nd[root], nd[ll], nd[rr]); } void mreverse(int x, int y, int l, int r, int root) { if (x<= l && y>= r) { node &k = nd[root]; swap(k.sum[0], k.sum[1]); swap(k.lf[0], k.lf[1]); swap(k.rt[0], k.rt[1]); swap(k.mx[0], k.mx[1]); switch (k.sn) { case -1: k.sn = 2; break; case 0: k.sn = 1; break; case 1: k.sn = 0; break; case 2: k.sn = -1; break; } return; } pushDown(root); int mid; if (x <= m) mreverse(x,y,lson); if (y > m) mreverse(x,y,rson); solve(nd[root], nd[ll], nd[rr]); } int querynum1(int x, int y, int l, int r, int root) { if (nd[root].sum[1] == nd[root].len) return y-x+1; if (nd[root].sum[0] == nd[root].len) return 0; int sum = 0; if (x <= l && y>= r) return nd[root].sum[1]; pushDown(root); int mid; if (y<= m) return querynum1(x,y,lson); if (x > m) return querynum1(x,y,rson); return querynum1(x,m,lson)+querynum1(m+1,y,rson); } node queryMX1(int x, int y, int l, int r, int root) { node res; if (x <= l && y >= r) { return nd[root]; } pushDown(root); int mid; if (y <= m) return queryMX1(x,y,lson); if (x > m) return queryMX1(x,y,rson); node a = queryMX1(x,m,lson); node b = queryMX1(m+1,y,rson); res.l = a.l; res.r = b.r; res.len = a.len+b.len; solve(res, a, b, 1); return res; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; int n, m; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 0; i< n; ++i) { scanf("%d", &num[i]); } build(0,n-1,1); while (m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if (a < 2) change(b,c,a,0,n-1,1); else if (a == 2) mreverse(b,c,0,n-1,1); else if (a == 3) printf("%d\n", querynum1(b,c,0,n-1,1)); else { node tp = queryMX1(b,c,0,n-1,1); printf("%d\n", tp.mx[1]); } } } return 0; }
这道题算是偏向于隐含的线段树,利用插入动态维护某个范围内的最大值,借鉴了别人的方法#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; // 4366 typedef __int64 LL; #define ll (rot<<1) #define rr (ll | 1) #define mid mm = (l+r)>>1 #define lson l,mm,ll #define rson mm+1,r,rr const int MAXN = 50005; map<int , int > mmp; int mxnum[MAXN*3]; int all; struct Edge { int to, next; }edge[MAXN*2]; int head[MAXN], cnt; void edd(int u, int v) { edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++; } struct mStaff { int id, loya, abili; bool operator < (const mStaff & a) const { if (abili != a.abili) return abili > a.abili; return id > a.id; } }staff[MAXN]; int frm[MAXN], ed[MAXN]; void build(int l, int r, int rot) { mxnum[rot] = -1; if (l == r) return; int mid; build(lson); build(rson); } // 更新到底 void add(int kk, int x, int l, int r, int rot) { if (l == r) { mxnum[rot] = kk; return; } int mid; if (x <= mm) add(kk, x, lson); if (x > mm) add(kk, x, rson); mxnum[rot] = max(mxnum[ll], mxnum[rr]); } int query(int x, int y, int l, int r, int rot) { if (x <= l && y >= r ) { return mxnum[rot]; } int mid; int s1 = -1, s2 = -1; if (x <= mm) s1 = query(x, y, lson); if (y > mm) s2 = query(x, y, rson); return max(s1, s2); } void dfs(int u) { frm[u] = all++; for (int i = head[u]; ~i; i = edge[i].next) dfs(edge[i].to); ed[u] = all-1; } int res[MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { int n, m; scanf("%d%d", &n, &m); cnt = 0; all = 0; memset(head, -1, sizeof head); mmp.clear(); for (int i = 1; i < n; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edd(a, i); staff[i].id = i; staff[i].loya = b; staff[i].abili = c; mmp[b] = i; } sort(staff+1, staff+n); dfs(0); build(0, n-1, 1); int k; for (int i = 1; i< n; i = k) { k = i; while (k < n && staff[k].abili == staff[i].abili) { int j = staff[k].id; int lo = query(frm[j], ed[j], 0, n-1, 1); if (lo == -1) res[j] = -1; else res[j] = mmp[lo]; ++k; } k = i; while (k < n && staff[k].abili == staff[i].abili) { int j = staff[k].id; add(staff[k].loya, frm[j], 0, n-1, 1); ++k; } } while (m--) { int a; scanf("%d", &a); printf("%d\n", res[a]); } } return 0; }
线段树中数据离散化的应用#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; typedef __int64 LL; #define ll (rot<<1) #define rr (ll | 1) #define mid mm = (l+r)>>1 #define lson l,mm,ll #define rson mm+1,r,rr const int MAXN = 200005; int n, m; int ttm[MAXN]; map<int, int> mmp; struct mNode { int u, v; }flower[MAXN]; int duan[MAXN*6], sz[MAXN*6]; void build(int l, int r, int rot) { duan[rot] = 0; sz[rot] = 0; if (l == r) return; int mid; build(lson); build(rson); } void pushDown(int rot) { if (!sz[rot]) return; duan[ll] += sz[rot]; duan[rr] += sz[rot]; sz[ll] += sz[rot]; sz[rr] += sz[rot]; sz[rot] = 0; } void add(int x, int y, int l, int r, int rot) { if (x<= l && y>= r) { duan[rot]++; sz[rot]++; return; } pushDown(rot); int mid; if (x <= mm) add(x, y, lson); if (y > mm) add(x, y, rson); duan[rot] = duan[ll] + duan[rr]; } int query(int x, int l, int r, int rot) { if (l == r) return duan[rot]; pushDown(rot); int mid; if (x <= mm) return query(x, lson); else return query(x, rson); } int ques[MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); for (int _ = 1; _ <= t; ++_) { printf("Case #%d:\n", _); scanf("%d%d", &n, &m); int all = 0; for (int i = 0; i< n; ++i) { int a, b; scanf("%d%d", &a, &b); flower[i].u = a; flower[i].v = b; ttm[all++] = a; ttm[all++] = b; } for (int j = 0; j< m; ++j) { int a; scanf("%d", &a); ques[j] = a; ttm[all++] = a; } int cnt = 1; sort(ttm, ttm+all); all = unique(ttm, ttm+all) - ttm; for (int i = 0; i< all; ++i) { mmp[ttm[i]] = i; } build(0, all-1, 1); for (int i = 0; i< n; ++i) { int a = mmp[flower[i].u]; int b = mmp[flower[i].v]; add(a, b, 0, all-1, 1); } for (int i = 0; i< m; ++i) { printf("%d\n", query(mmp[ques[i]], 0, all-1, 1)); } } return 0; }
hdu 4391 Paint The Wall
线段树成段更新,成段查询
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; typedef __int64 LL; #define ll (rot<<1) #define rr (ll | 1) #define mid mm = (l+r)>>1 #define lson l,mm,ll #define rson mm+1,r,rr const int MAXN = 200005; int n, m; int mxc[MAXN*3], mnc[MAXN*3], sz[MAXN*3]; int colr[MAXN]; void build(int l, int r, int rot) { sz[rot] = 0; if (l == r) { mxc[rot] = mnc[rot] = colr[l]; return; } int mid; build(lson); build(rson); mxc[rot] = max(mxc[ll], mxc[rr]); mnc[rot] = min(mnc[ll], mnc[rr]); } void pushDown(int rot) { if (sz[rot]) { sz[rot] = 0; mxc[ll] = mxc[rr] = mxc[rot]; mnc[ll] = mnc[rr] = mnc[rot]; sz[ll] = sz[rr] = 1; } } void update(int c, int x, int y, int l, int r, int rot) { if (c == mxc[rot] && c == mnc[rot]) return; if (x <= l && y >= r) { mxc[rot] = mnc[rot] = c; sz[rot] = 1; return; } pushDown(rot); int mid; if (x <= mm ) update(c, x, y, lson); if (y > mm) update(c, x, y, rson); mxc[rot] = max(mxc[ll], mxc[rr]); mnc[rot] = min(mnc[ll], mnc[rr]); } int query(int c, int x, int y, int l, int r, int rot) { if (c < mnc[rot] || c > mxc[rot]) return 0; if (c == mxc[rot] && c == mnc[rot]) return (y-x+1); if (l == r) return mxc[rot] == c; pushDown(rot); int mid; if (y <= mm) return query(c, x, y, lson); else if (x > mm) return query(c, x, y, rson); else return query(c, x, mm, lson) + query(c, mm+1, y, rson); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d%d", &n, &m) != EOF) { for (int i = 0; i< n; ++i) { scanf("%d", colr+i); } build(0, n-1, 1); while (m--) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); if (a == 1) update(d, b, c, 0, n-1, 1); else printf("%d\n", query(d, b, c, 0, n-1, 1)); } } return 0; }