简介
基于个人对线段树的理解,线段树的核心思想就在于离散化和滞后性
hdu 1166 敌兵布阵(入门级)
hdu 1542 Atlantis
将线段离散化,自己一开始利用线段树将沿y坐标的矩阵归并可惜总是wa,最后借鉴了别人的方法
#include <cstdio> #include <algorithm> using namespace std; const int MAXN = 5000; double MM[MAXN]; double sum; struct node { double len; int bz; }data[MAXN<<2]; struct line { double x1, x2, y; int typ; bool operator < (const line & a) const { if (y != a.y) return y < a.y; return typ > a.typ; } }mLine[MAXN*2]; #define ll (cnt<<1) #define rr ((cnt<<1)|1) #define lson l,m,ll #define rson m,r,rr #define mid m=(l+r)>>1 void build(int l, int r, int cnt) { data[cnt].bz = 0; data[cnt].len = 0.0; if (l+1 == r) return; int mid; build(lson); build(rson); } void pushUP (int l, int r, int cnt ) { if (data[cnt].bz) data[cnt].len = MM[r] - MM[l]; else { if (l+1 == r) data[cnt].len = 0.0; else data[cnt].len = data[ll].len + data[rr].len; } } void solve(int t, int x1, int x2, int l, int r, int cnt) { if (x1 <= l && x2 >= r) { data[cnt].bz += t; pushUP(l, r, cnt); return; } if (l+1 == r) return; int mid; if (x1 < m) solve(t, x1, x2, lson); if (x2 > m) solve(t, x1, x2, rson); pushUP(l, r, cnt); } int n, m, d; int mfind(double c) { int p, q; p = 0; q = d - 1; while( p <= q ) { int md=(p+q)/2; if(MM[md]==c) return md; if(MM[md]<c) p=md+1; else q=md-1; } return -1; } int main() { int cs = 0; while (scanf("%d", &n) != EOF && n) { m = 0; sum = 0.0; double x1, y1, x2, y2; for (int i = 0; i< n; ++i) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); if ( (y2-y1)*(x2-x1) == 0.0) continue; line tp; tp.x1 = x1; tp.x2 = x2; tp.y = y1; tp.typ = 1; MM[m] = x1; mLine[m++] = tp; tp.y = y2; tp.typ = -1; MM[m] = x2; mLine[m++] = tp; } sort(mLine, mLine+m); sort(MM, MM+m); d = 1; for (int i = 1; i< m; ++i) { if (MM[i] != MM[d-1]) { MM[d++] = MM[i]; } } build(0, d-1, 1); for (int i = 0; i< m-1; ++i) { int a = mfind(mLine[i].x1); int b = mfind(mLine[i].x2); solve(mLine[i].typ, a, b, 0, d-1, 1); sum += data[1].len * (mLine[i+1].y - mLine[i].y); } printf("Test case #%d\n", ++cs); printf("Total explored area: %.2lf\n\n", sum); } return 0; }
题目有个陷阱,实际上段数等于h和n的最小值就可以
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; #ifdef __GNUC__ #define LL long long #else #define LL __int64 #endif const int MAXN = 200005; #define ll (cnt<<1) #define rr ((cnt<<1)|1) #define lson l,md,ll #define rson md+1,r,rr #define mid md=(l+r)>>1 int h, w, n; int mxNum[MAXN*3]; void build(int l, int r, int cnt) { mxNum[cnt] = w; if (l == r) return; int mid; build(lson); build(rson); } int solve(int a, int l, int r, int cnt) { if (l == r) { mxNum[cnt] -= a; return l; } int e; int mid; if (mxNum[ll] >= a) { e = solve(a, lson); } else { e = solve(a, rson); } mxNum[cnt] = max(mxNum[ll], mxNum[rr]); return e; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d%d%d", &h, &w, &n) != EOF) { h = min(h, n); build(1, h, 1); while (n--) { int a, b; scanf("%d", &a); if (a > mxNum[1]) b = -1; else { b = solve(a, 1, h, 1); } printf("%d\n", b); } } return 0; }
hdu 3308 LCIS
线段树合并,算是基础上的稍加变化
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; // hdu 3308 #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 = 100005<<2; struct mNode { int l, r; int lf, rt, md; }node[MAXN]; int num[MAXN]; int n, m; inline void solve(mNode *a, mNode *bl, mNode *br) { a->md = max(bl->md, br->md); int mm = bl->r; if (num[mm] < num[1+mm]) { int k = bl->rt + br->lf; a->md = max(a->md, k); if (bl->lf == (bl->r-bl->l+1)) { a->lf = bl->lf + br->lf; } else { a->lf = bl->lf; } if (br->rt == (br->r-mm)) { a->rt = bl->rt + br->rt; } else { a->rt = br->rt; } } else { a->lf = bl->lf; a->rt = br->rt; } } void build(int l, int r, int rot) { node[rot].l = l; node[rot].r = r; if (l == r) { node[rot].lf = node[rot].rt= node[rot].md = 1; return; } int mid; build(lson); build(rson); solve(node+rot, node+(ll), node+(rr)); } void change(int a, int b, int l, int r, int rot) { if (l == r) { num[l] = b; node[rot].lf = node[rot].rt= node[rot].md = 1; return; } int mid; if (a <= mm) change(a, b, lson); else change(a, b, rson); solve(node+rot, node+(ll), node+(rr)); } mNode query(int x, int y, int l, int r, int rot) { mNode res, a, b; if (x <= l && y >= r) { return node[rot]; } int mid; if (y <= mm) { return query(x, y, lson); } if (x > mm) { return query(x, y, rson); } a = query(x, y, lson); b = query(x, y, rson); res.l = a.l; res.r = b.r; solve(&res, &a, &b); return res; } char c[5]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); for(int i = 0; i< n; ++i) { int a; scanf("%d", num+i); } build(0, n-1, 1); while (m--) { int a, b; scanf("%s%d%d", c, &a, &b); if (c[0] == 'U') { change(a, b, 0, n-1, 1); } else { mNode res = query(a, b, 0, n-1, 1); printf("%d\n", res.md); } } } return 0; }
hdu 4027 Can you answer these queries?
线段树应用,但题目的突破口是 2^63 最多被开方6次
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; // hdu 4027 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 = 100005<<2; struct mNode { LL all; int flg; }data[MAXN]; LL num[MAXN]; void build(int l, int r, int rot) { data[rot].flg = 0; if (l == r) { data[rot].all = num[l]; if (num[l] == 1) data[rot].flg = 1; return; } int mid; build(lson); build(rson); data[rot].all = data[ll].all + data[rr].all; data[rot].flg = data[ll].flg & data[rr].flg; } void add(int x, int y, int l, int r, int rot) { if (data[rot].flg) return; if (l == r) { data[rot].all = (LL)sqrt(data[rot].all); if (data[rot].all == 1) data[rot].flg = 1; return; } int mid; if (x <= mm) add(x, y, lson); if (y > mm) add(x, y, rson); data[rot].all = data[ll].all + data[rr].all; data[rot].flg = data[ll].flg & data[rr].flg; } LL query(int x, int y, int l, int r, int rot) { LL sum = 0; if (x <= l && y >= r ) { return data[rot].all; } int mid; if (x <= mm) sum += query(x, y, lson); if (y > mm) sum += query(x, y, rson); return sum; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, t = 0; while (scanf("%d", &n) != EOF) { printf("Case #%d:\n", ++t); for (int i = 1; i<= n; ++i) { scanf("%I64d", &num[i]); } build(1, n, 1); int k; scanf("%d", &k); while (k--) { int a, b, c, d, e; scanf("%d%d%d", &a, &d, &e); b = min(d, e); c = max(d, e); if (a == 0) { add(b, c, 1, n, 1); } else { printf("%I64d\n", query(b, c, 1, n, 1)); } } puts(""); } return 0; }hdu 3974 Assign the task
简单题#include <cstdio> #include <iostream> #include <cmath> using namespace std; /* acm.hdu.edu.cn/showproblem.php?pid=3974 */ const int MAXN = 50005*2; #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 lf[MAXN], rt[MAXN], cnt; struct Edge { int v, next; }edge[MAXN*2]; int head[MAXN], e, fa[MAXN]; int data[MAXN*2], sz[MAXN*2]; void m_init() { memset(head, -1, sizeof head); memset(fa, -1, sizeof fa); e = cnt = 0; } void add(int u, int v) { fa[v] = u; edge[e].v = v; edge[e].next = head[u]; head[u] = e++; } void build(int l, int r, int root) { data[root] = -1; sz[root] = 0; if (l == r) return; int mid; build(lson); build(rson); } void pushDown(int root) { if (!sz[root]) return; sz[root] = 0; data[ll] = data[rr] = data[root]; sz[ll] = sz[rr] = 1; } void change(int c, int x, int y, int l, int r, int root) { if (x <= l && y >= r) { data[root] = c; sz[root] = 1; return; } pushDown(root); int mid; if (x <= m) change(c,x,y,lson); if (y > m) change(c,x,y,rson); } int query(int x, int l, int r, int root) { if (l == r) return data[root]; pushDown(root); int mid; if (x <= m) return query(x,lson); if (x > m) return query(x,rson); } void dfs(int u) { lf[u] = cnt++; for (int i= head[u]; ~i; i = edge[i].next) { dfs(edge[i].v); } rt[u] = cnt-1; } char str[3]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t, cs = 0; int n, m; scanf("%d", &t); while (t--) { printf("Case #%d:\n", ++cs); m_init(); scanf("%d", &n); for (int i = 1; i< n; ++i) { int v, u; scanf("%d%d", &v, &u); add(u,v); } int k; for (int i = 1; i<= n; ++i) { if (fa[i] == -1) { k = i; break; } } dfs(k); build(0, cnt-1, 1); scanf("%d", &m); while (m--) { int a, b; scanf("%s", str); if (str[0] == 'C') { scanf("%d", &a); printf("%d\n", query(lf[a],0,cnt-1,1)); } else { scanf("%d%d", &a, &b); change(b, lf[a], rt[a], 0, cnt-1, 1); } } } return 0; }