HDU 1540 Tunnel Warfare (线段树 / 求最大连续区间长度)

2023-10-31 20:08

本文主要是介绍HDU 1540 Tunnel Warfare (线段树 / 求最大连续区间长度),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门

题意: 抗日战争时期,华北平原广大地区进行了广泛的隧道战争。一般来说,通过隧道连接的村庄成一直线。除了两端的两个村外,每个村庄都与两个相邻的村直接相连。
入侵者经常对一些村庄发动袭击,并摧毁其中的部分隧道。八路军指挥官要求提供隧道和村庄的最新连接状态。如果某些村庄被严重隔离,则必须立即恢复连接!

输入:
输入的第一行包含两个正整数n和m(n,m≤50,000),表示村庄和事件的数量。接下来的m行中的每行都描述一个事件。
下面以不同的格式描述了三个不同的事件:

D x:第x个村庄被摧毁。
问:陆军司令部要求第x个村庄包括其自身直接或间接联系的村庄数。
R:最后被摧毁的村庄被重建。

思路: 就是个常规线段树题目,和acwing上的你能回答这些问题吗做法原理相似。

代码实现:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <functional>
#define null NULL
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
using namespace std;
const int  inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int   mod = 1e9 + 7;
const int  N = 50005;int n, m, x, tt;
char op[3];
stack<int> st;struct node{int l, r;int lmax, rmax, tmax;
}tr[N << 2];//区间合并
void pushdown(int u){tr[u].lmax = tr[u << 1].lmax;tr[u].rmax = tr[u << 1 | 1].rmax;if(tr[u << 1].lmax == tr[u << 1].r - tr[u << 1].l + 1) tr[u].lmax = tr[u << 1].lmax + tr[u << 1 | 1].lmax;if(tr[u << 1 | 1].rmax == tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) tr[u].rmax = tr[u << 1].rmax + tr[u << 1 | 1].lmax;tr[u].tmax = max(tr[u].rmax, tr[u].lmax);tr[u].tmax = max(tr[u].tmax, tr[u << 1].rmax + tr[u << 1 | 1].lmax);
}void build(int u, int l, int r)
{int t = r - l + 1;tr[u] = {l, r, t, t, t};if(l == r) return;int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);
}void modify(int u, int x, int v)
{if(tr[u].l == x && tr[u].r == x){tr[u].lmax = tr[u].rmax = tr[u].tmax = v;return;}int mid = tr[u].l + tr[u].r >> 1;if(x <= mid) modify(u << 1, x, v);else modify(u << 1 | 1, x, v);//主义在修改后将两个区间合并pushdown(u);
}int query(int u, int x)
{if(!tr[u].tmax) return 0;//在左端区间if(x < tr[u].l + tr[u].lmax)return tr[u].lmax;//在右端区间if(x > tr[u].r - tr[u].rmax)return tr[u].rmax;//在两个区间的中间if(x > tr[u << 1].r - tr[u << 1].rmax && x < tr[u << 1 | 1].l + tr[u << 1 | 1].lmax)return tr[u << 1].rmax + tr[u << 1 | 1].lmax;int mid = tr[u].l + tr[u].r >> 1;if(x <= mid) return query(u << 1, x);else return query(u << 1 | 1, x);
}int main()
{while(~scanf("%d%d", &n, &m)){while(!st.empty()) st.pop();build(1, 1, n);while(m --){scanf("%s", op);if(*op == 'D'){scanf("%d", &x);st.push(x);modify(1, x, 0);}else if(*op == 'Q'){scanf("%d", &x);printf("%d\n", query(1, x));}else if(!st.empty()){x = st.top(); st.pop();modify(1, x, 1);}}}return 0;
}

这篇关于HDU 1540 Tunnel Warfare (线段树 / 求最大连续区间长度)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/317800

相关文章

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while