现在的位置: 首页 > 综合 > 正文

线段树合集 II

2017年12月16日 ⁄ 综合 ⁄ 共 8805字 ⁄ 字号 评论关闭

hdu 4553 约会安排

段更新里稍微复杂的应用,需要设置多个判断标志,当时比赛的时候没做出来,还是挺烦人的

hdu 3397 Sequence operation

题目比较烦人,考察对线段树的理解
#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;
}

hdu 4366 Successor

这道题算是偏向于隐含的线段树,利用插入动态维护某个范围内的最大值,借鉴了别人的方法
#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;
}

hdu 4325 Flowers

线段树中数据离散化的应用
#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;
}

抱歉!评论已关闭.