hdu-1540(线段树+区间合并)

Posted wyh344866

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu-1540(线段树+区间合并)相关的知识,希望对你有一定的参考价值。

Tunnel Warfare

HDU - 1540

思路:

没被摧毁的村庄为1,否则为0,用len记录

线段树维护区间的两个信息:

前缀最长1的序列pre

后缀最长1的序列suf

父节点与左右子节点的关系:

//lc为左节点,rc为右节点

1.若左右结点都不满1,则tr[p].pre = tr[lc].pre,tr[p].suf = tr[rc].suf

2.若左节点满1,tr[p].pre = tr[lc].pre + tr[rc].pre;

3.若右节点满1,tr[p].suf = tr[lc].suf + tr[rc].suf;

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<algorithm>
#include<fstream>
#include<iostream>
#include<cstdio>
#include<deque>
#include<string>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<unordered_map>
using namespace std;
#define INF 2e9
#define MAXN 310000
#define N 1000010
#define M 10007
#define endl \'\\n\'
#define exp 1e-8
#define lc p << 1
#define rc p << 1|1
#define lowbit(x) ((x)&-(x))
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
inline ULL read() 
	ULL x = 0, f = 1;
	char ch = getchar();
	while (ch < \'0\' || ch>\'9\') 
		if (ch == \'-\')
			f = -1;
		ch = getchar();
	
	while (ch >= \'0\' && ch <= \'9\') 
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	
	return x * f;

void print(ULL x) 
	if (x > 9)print(x / 10);
	putchar(x % 10 ^ 48);

int n, m,idx,his[N];
struct tree

	int l, r, len, pre, suf;
tr[N*4];
void pushup(int p)

	int len = tr[p].r - tr[p].l + 1;
	tr[p].pre = tr[lc].pre;
	tr[p].suf = tr[rc].suf;
	if (len - (len >> 1) == tr[lc].pre) tr[p].pre = tr[lc].pre + tr[rc].pre;
	if (len >> 1 == tr[rc].suf) tr[p].suf = tr[lc].suf + tr[rc].suf;


void build(int p, int l, int r)

	tr[p].l = l, tr[p].r = r;
	if (l == r)
	
		tr[p].len = tr[p].pre = tr[p].suf = 1;
		return;
	
	int m = l + r >> 1;
	build(lc, l, m);
	build(rc, m + 1, r);
	pushup(p);

void update(int p, int x,int c )

	if (tr[p].l == tr[p].r)
	
		tr[p].suf = tr[p].pre = tr[p].len = c;
		return;
	
	int m = tr[p].l + tr[p].r >> 1;
	if (x <= m)update(lc, x, c);
	else  update(rc, x, c);
	pushup(p);

int query(int p, int x)

	if (tr[p].l == tr[p].r)
		return tr[p].len;
	int m = tr[p].l + tr[p].r >> 1;
	if (x <= m)
	
		if (x > m - tr[lc].suf)return tr[lc].suf + tr[rc].pre;
		else return query(lc, x);
	
	else
	
		if (x <= m + tr[rc].pre)return tr[lc].suf + tr[rc].pre;
		else return query(rc, x);
	

int main()

	while (scanf("%d%d", &n, &m) != EOF)
	
		build(1, 1, n);
		idx = 0;
		while (m--)
		
			char a;
			int x;
			cin >> a;
			if (a == \'D\')
			
				scanf("%d", &x);
				his[++idx] = x;
				update(1, x, 0);
			
			else if (a == \'Q\')
			
				scanf("%d", &x);
				printf("%d\\n", query(1, x));
			
			else
			
				x= his[idx--];
				update(1, x, 1);
			
		
	
	return 0;

HDU 3308 LCIS (线段树区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308

题目很好懂,就是单点更新,然后求区间的最长上升子序列。

线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int MAXN = 1e5 + 5;
 6 struct SegTree {
 7     int l , r , lsum , sum , rsum;
 8 }T[MAXN << 2];
 9 int a[MAXN];
10 
11 void pushup(int p) {
12     int ls = p << 1 , rs = (p << 1)|1 , mid = (T[p].r + T[p].l) >> 1;
13     T[p].lsum = T[ls].lsum , T[p].rsum = T[rs].rsum;
14     if(T[p].lsum == T[ls].r - T[ls].l + 1) {
15         T[p].lsum += (a[mid + 1] > a[mid] ? T[rs].lsum : 0);
16     }
17     if(T[p].rsum == T[rs].r - T[rs].l + 1) {
18         T[p].rsum += (a[mid + 1] > a[mid] ? T[ls].rsum : 0);
19     }
20     T[p].sum = max(T[ls].sum , T[rs].sum);
21     int temp = (a[mid + 1] > a[mid] ? T[ls].rsum + T[rs].lsum : 1);
22     T[p].sum = max(temp , T[p].sum);
23 }
24 
25 void build(int p , int l , int r) {
26     int mid = (l + r) >> 1;
27     T[p].l = l , T[p].r = r;
28     if(l == r) {
29         T[p].lsum = T[p].rsum = T[p].sum = 1;
30         return ;
31     }
32     build(p << 1 , l , mid);
33     build((p << 1)|1 , mid + 1 , r);
34     pushup(p);
35 }
36 
37 void updata(int p , int pos , int num) {
38     int mid = (T[p].l + T[p].r) >> 1;
39     if(T[p].l == T[p].r && T[p].l == pos) {
40         a[pos] = num;
41         return ;
42     }
43     if(pos <= mid) {
44         updata(p << 1 , pos , num);
45     }
46     else {
47         updata((p << 1)|1 , pos , num);
48     }
49     pushup(p);
50 }
51 
52 int query(int p , int l , int r) {
53     int mid = (T[p].l + T[p].r) >> 1;
54     if(l == T[p].l && T[p].r == r) {
55         return T[p].sum;
56     }
57     if(r <= mid) {
58         return query(p << 1 , l , r);
59     }
60     else if(l > mid) {
61         return query((p << 1)|1 , l , r);
62     }
63     else {
64         return max((a[mid + 1] > a[mid] ? min(mid - l + 1 , T[p << 1].rsum) + min(T[(p << 1)|1].lsum , r - mid) : 1) ,
65          max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r) ) );
66     }
67 }
68 
69 int main()
70 {
71     int t , n , m;
72     scanf("%d" , &t);
73     while(t--) {
74         scanf("%d %d" , &n , &m);
75         for(int i = 1 ; i <= n ; ++i) {
76             scanf("%d" , a + i);
77         }
78         build(1 , 1 , n);
79         char q[5];
80         int l , r;
81         while(m--) {
82             scanf("%s %d %d" , q , &l , &r);
83             if(q[0] == Q) {
84                 printf("%d\n" , query(1 , l + 1 , r + 1));
85             }
86             else {
87                 updata(1 , l + 1 , r);
88             }
89         }
90     }
91     return 0;
92 }

 

以上是关于hdu-1540(线段树+区间合并)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1540 Tunnel Warfare(区间合并)线段树

hdu 1540(线段树区间合并)

hdu--1540 Tunnel Warfare(线段树+区间合并)

线段树区间合并HDU1540-Tunnel Warfare

hdu-1540(线段树+区间合并)

HDU 1540 Tunnel Warfare 线段树区间合并