HDU-1540 Tunnel Warfare(区间连续点长度)
http://acm.hdu.edu.cn/showproblem.php?pid=1540
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
Input
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
Output
Sample Input
D
D
D
Q
Q
R
Q
R
Q
Sample Output
题意:
一条线上有n个点,一共有m个操作,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
这题有点坑,注意是多样例输入
解法一(421ms、4.3MB):
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; struct node
{
int l;
int r;
int ls;//ls为左端最大连续区间
int rs;//rs为右端最大连续区间
int ms;//ms区间内最大连续区间
}SegTree[<<]; int n,m,x;
stack<int> sk; void PushUp(int rt)
{
SegTree[rt].ls=SegTree[rt<<].ls;//左区间
SegTree[rt].rs=SegTree[rt<<|].rs;//右区间
//父亲区间内的最大区间必定是,左子树最大区间,右子树最大区间,左右子树合并的中间区间,三者中最大的区间值
SegTree[rt].ms=max(max(SegTree[rt<<].ms,SegTree[rt<<|].ms),SegTree[rt<<].rs+SegTree[rt<<|].ls);
if(SegTree[rt<<].ms==SegTree[rt<<].r-SegTree[rt<<].l+)//左子树区间满了的话,父亲左区间要加上右孩子的左区间
SegTree[rt].ls+=SegTree[rt<<|].ls;
if(SegTree[rt<<|].ms==SegTree[rt<<|].r-SegTree[rt<<|].l+)//同理
SegTree[rt].rs+=SegTree[rt<<].rs;
} void Build(int l,int r,int rt)
{
SegTree[rt].l=l;
SegTree[rt].r=r;
SegTree[rt].ls=SegTree[rt].rs=SegTree[rt].ms=r-l+;
if(l==r)
return ;
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
} void Update(int L,int f,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(l==r)
{
if(f==)
SegTree[rt].ls=SegTree[rt].rs=SegTree[rt].ms=;//修复
else if(f==)
SegTree[rt].ls=SegTree[rt].rs=SegTree[rt].ms=;//破坏
return ;
}
int mid=(l+r)>>;
if(L<=mid)
Update(L,f,rt<<);
else if(L>mid)
Update(L,f,rt<<|);
PushUp(rt);
} int Query(int L,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(l==r||SegTree[rt].ms==||SegTree[rt].ms==r-l+)//到了叶子节点或者该访问区间为空或者已满都不必要往下走了
return SegTree[rt].ms;
int mid=(l+r)>>;
if(L<=mid)
{
//因为L<=mid,看左子树,SegTree[rt<<1].r-SegTree[rt<<1].rs+1代表左子树右边连续区间的左边界值,如果t在左子树的右区间内,则要看右子树的左区间有多长并返回
if(L>=SegTree[rt<<].r-SegTree[rt<<].rs+)
return Query(L,rt<<)+Query(mid+,rt<<|);
else
return Query(L,rt<<);//如果不在左子树的右边界区间内,则只需要看左子树
}
else
{
if(L<=SegTree[rt<<|].l+SegTree[rt<<|].ls-)//同理
return Query(L,rt<<|)+Query(mid,rt<<);
else
return Query(L,rt<<|);
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
Build(,n,);
char c[];
while(!sk.empty())
sk.pop();
while(m--)
{
scanf("%s",c);
if(c[]=='D')
{
scanf("%d",&x);
sk.push(x);
Update(x,,);
}
else if(c[]=='Q')
{
scanf("%d",&x);
printf("%d\n",Query(x,));
}
else if(c[]=='R')
{
if(!sk.empty())
{
x=sk.top();
sk.pop();
Update(x,,);
}
}
}
}
return ;
}
解法二(483ms、3.8MB):
原文地址:https://blog.csdn.net/chudongfang2015/article/details/52133243
该思路比较简单,就是利用线段数求区间最大和最小值。
只不过每个点最初的最大最小值不是他们自身,村子如果没有被摧毁,最大、最小值是分别用0(求最大值时)和n+1(求最小值时)代替的(下方会有所解释)。
当村子被摧毁时,更新该结点最大最小值为该村子本身编号。
我们求的区间最大值时就是在区间[1,x]中查找被摧毁的村子中编号最大的一个,求区间最小值时就是在区间[x,n]中查找被摧毁的村子中编号最小的一个。
下面给出一些例子(红色代表被摧毁)
这里假设其为 1 3 4 6 7
则如果 其中有若干个村子被毁了,如果要求第4个村子
只需求出来 1->4区间中被毁村子的最大值(2),
和 4->7 区间中被毁村子的最小值(5),
根据两者求出村子的连续区间,即 2->5 所以其村子连续个数 为 5-2-1 = 2
即mmin - mmax -1(正常求区间长度为r-l+1,因为这个区间内左右端点均为被摧毁的点,故长度-2,最终为r-l+1-2即r-l-1)
特殊情况: 如果1 3 4 6 7 求2的连续区间 ,其最大为2,最小也为2(2-2-1=-1,应为零,故当成特殊情况对待,则其连续个数为 0 )
这里注意,对于没有被摧毁的村子,不加入到线段数节点,而是分别用0(求最大值时)和n+1(求最小值时)代替,
代表被摧毁的村子最小值为0,最大值为n+1,而不存在这两个编号的村子,故相当于这段区间无被摧毁的村子。
这样能保证,其不影响加入村子的求极值,而且最其在没有村子被摧毁的情况下,也能正确的求出解。
例子: 1 2 3 5 6 7
求村子3的连续区间,这里1->3 maxx为0 ; 3->n minn为4
所以其连续空间为4-0-1 =3 为正解
可以自己再试其他例子
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
//const double PI=acos(-1);
const int maxn=1e5+;
using namespace std;
//ios::sync_with_stdio(false);
// cin.tie(NULL); struct node
{
int l;
int r;
int MAX;
int MIN;
}SegTree[<<]; int n,m,x;
stack<int> sk; void PushUp(int rt)
{
SegTree[rt].MAX=max(SegTree[rt<<].MAX,SegTree[rt<<|].MAX);
SegTree[rt].MIN=min(SegTree[rt<<].MIN,SegTree[rt<<|].MIN);
} void Build(int l,int r,int rt)//建树
{
SegTree[rt].l=l;
SegTree[rt].r=r;
if(l==r)
{
SegTree[rt].MAX=;
SegTree[rt].MIN=n+;
return ;
}
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
PushUp(rt);
} void Update(int L,int T,int rt)//更新
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(l==r)
{
if(T==-)//-1表示恢复, 如果恢复,就把对应的值改为0或n+1
{
SegTree[rt].MAX=;
SegTree[rt].MIN=n+;
}
else
SegTree[rt].MAX=SegTree[rt].MIN=T;
return ;
}
int mid=(l+r)>>;
if(L<=mid)
Update(L,T,rt<<);
else
Update(L,T,rt<<|);
PushUp(rt);
} int Query_MAX(int L,int R,int rt)//查找区间最大值
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(L<=l&&R>=r)
{
return SegTree[rt].MAX;
}
int MAX=;
int mid=(l+r)>>;
if(L<=mid)
MAX=max(MAX,Query_MAX(L,R,rt<<));
if(R>mid)
MAX=max(MAX,Query_MAX(L,R,rt<<|));
return MAX;
} int Query_MIN(int L,int R,int rt)//查找区间最小值
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(L<=l&&R>=r)
{
return SegTree[rt].MIN;
}
int MIN=INF;
int mid=(l+r)>>;
if(L<=mid)
MIN=min(MIN,Query_MIN(L,R,rt<<));
if(R>mid)
MIN=min(MIN,Query_MIN(L,R,rt<<|));
return MIN;
} int main()
{
while(~scanf("%d %d",&n,&m))
{
Build(,n,);
char c[];
while(!sk.empty())
sk.pop();
while(m--)
{
scanf("%s",c);
if(c[]=='D')
{
scanf("%d",&x);
sk.push(x);
Update(x,x,);//更新线段数的值,把x对应的值更新成x
}
else if(c[]=='Q')
{
scanf("%d",&x);
int mmax,mmin;
mmax=Query_MAX(,x,);
mmin=Query_MIN(x,n,);
if(mmax==mmin)//考虑特殊情况
printf("%d\n",);
else
printf("%d\n",mmin-mmax-);
}
else if(c[]=='R')
{
if(!sk.empty())
{
x=sk.top();
sk.pop();
Update(x,-,);//如果恢复,就把对应的值改为0或n+1
}
}
}
}
return ;
}
HDU-1540 Tunnel Warfare(区间连续点长度)的更多相关文章
- hdu 1540 Tunnel Warfare (区间线段树(模板))
http://acm.hdu.edu.cn/showproblem.php?pid=1540 Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) ...
- HDU 1540 Tunnel Warfare(最长连续区间 基础)
校赛,还有什么途径可以申请加入ACM校队? Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/ ...
- hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并
Tunnel Warfare Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...
- hdu 1540 Tunnel Warfare (线段树 区间合并)
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- HDU 1540 Tunnel Warfare 线段树区间合并
Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...
- hdu 1540 Tunnel Warfare(线段树区间统计)
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- HDU 1540 Tunnel Warfare
HDU 1540 思路1: 树状数组+二分 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #d ...
- hdu 1540 Tunnel Warfare (线段树,维护当前最大连续区间)
Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively i ...
- hdu 1540 Tunnel Warfare 线段数区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) P ...
随机推荐
- x264报错No working C compiler found.
现象: 缺少C++部署包 解决 [root@localhost x264]# yum -y install gcc gcc-c++ kernel-devel [root@localhost x264] ...
- spring装配bean的三种方式及其混合装配
在spring容器中装配bean有三种基本方式和混合装配方式: 隐式的bean自动发现机制和自动装配 在java中进行显式配置 在xml中配置 混合装配(在多个java文件中配置.在JavaConfi ...
- part10 header界面渐隐渐显 //动态路由//项目动画
两个组件只同时显示一个 可以用 a v-show='variable' b: v-show='!variable' 1.对全局事件的解绑 //代码容易出现大量bug 因为影响其他组件 keep-al ...
- C语言的字符串类型
C语言使用指针来管理字符串(1)C语言中定义字符串的方法:char *p = "linux";此时p就叫字符串,但是实际上p只是一个字符指针(本质上就是一个指针变量,只是p指向了一 ...
- CNN:扩张卷积输出分辨率计算
扩张卷积(Dilated convolutions)是另一种卷积操作,也叫做空洞卷积(Atrous convolution).相比于普通的卷积,相同的卷积核,空洞卷积能够拥有更大的感受野. 相同的卷积 ...
- Centos6.5 安装zabbix3(收藏,非原创)
1.安装PHP Zabbix 3.0对PHP的要求最低为5.4,而CentOS6默认为5.3.3,完全不满足要求,故需要利用第三方源,将PHP升级到5.4以上,注意,不支持PHP7 rpm -ivh ...
- no.9亿级用户下的新浪微博平台架构读后感
微博平台的第三代技术体系,使用正交分解法建立模型:在水平方向,采用典型的三级分层模型,即接口层.服务层与资源层:在垂直方向,进一步细分为业务架构.技术架构.监控平台与服务治理平台. 水平分层 (1)接 ...
- Win10教育版VL版kms密钥激活
1.右键开始图标,或者win+x,选择Windows PowerShell(管理员): 2.依次执行下面的命令,分别表示安装win10教育版密钥,设置kms服务器,激活win10教育版: slmgr ...
- 最短路问题--P4779 单源最短路(标准版)Dijkstra堆优化
题目背景 2018 年7月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路. 最终,他因此没能与理想的大学达成契约. 小 F 衷心祝愿大家不再重 ...
- 删除xcode项目中不再使用的图片资源
1. 利用工具 下载地址 http://jeffhodnett.github.io/Unused/ 运行效果如下 2. 通过终端 执行 shell 命令 a. 第一步建立.sh 文件 如 ...