您的位置:首页 > 其它

线段树合集 I

2013-11-09 10:22 169 查看

简介

基于个人对线段树的理解,线段树的核心思想就在于离散化和滞后性

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;
}


hdu 2795 Billboard

题目有个陷阱,实际上段数等于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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: